Accept lvalue ref or rvalue ref - c++

I want to write some functions that take an Object as one of their arguments, whether by lvalue or rvalue ref doesn't matter - but definitely not by value and definitely only an Object. It seems like I have two options for this:
void foo(Object& o) {
// stuff
}
void foo(Object&& o) { foo(o); } // this is fine for my use-case
Or using universal references:
template <typename T, typename U>
using decays_to = typename std::is_same<std::decay_t<T>, U>::type;
template <typename T>
std::enable_if_t<decays_to<T, Object>::value>
foo(T&& o)
{
// same stuff as before
}
But the first option involves writing twice as many functions as I need, and the second option involves writing a bunch of template stuff which is seems like overkill to me (I kind of read that as accept anything for o - oh just kidding, really just an Object).
Is there a better way to solve this or am I just pretty much stuck with whichever one of these I feel less meh about?

There is a difference between your two implementations. The first will admit anything convertible to Object, Object&& or Object&. The second will only admit Object and things that inherit from it in rvalue or lvalue form (and reject const Objects, much like the first).
We can add a helper object:
template<class T>
struct l_or_r_value {
T& t;
l_or_r_value( T&& t_ ):t(t_) {}
l_or_r_value( T& t_ ):t(t_) {}
operator T&(){ return t; }
T* operator->(){ return &t; }
T& operator*(){ return t; }
T& get(){ return t; }
};
then we can write:
void foo(l_or_r_value<Object> o)
and we get behavior that is very close to your second solution, without the template mumbo jumbo at point of call. You do have to access *o and o-> or do a Object& o = o_; to get at the raw reference.
It is not like the first solution, because C++ does not chain two user-defined conversions.
The concepts proposal would add the ability to say "I take anything here, so long as it is an Object" with a more terse syntax.
Another approach would be to just take Object&, and use:
tepmlate<class T>
T& lvalue( T&& t) { return t; }
to convert rvalues to lvalues when you need to (you could also call it unmove to be cute)

The typical way to accept both lvalues and rvalues is to make a function that takes a const reference. That means you can't call non-const functions on the object, but if you want to pass rvalues such as temporaries, then calling non-const functions wouldn't necesarily make much sense anyway.

Related

Remove rvalueness, keep lvalue references (standard type trait available?)

I'm trying to write a function that returns a subset of a variadic argument pack under the form of an std::tuple. The function should ideally have no runtime overhead (no unnecessary copies), and it should allow users to access lvalue references and modify them.
Value types, lvalue references and const lvalue references should be maintained. Temporaries (rvalue references), should be "converted" to value types to avoid creating invalid references (references to temporaries).
Example of desired results:
int lr = 5;
const int& clr = lr;
auto t = make_subpack_tuple(lr, clr, 5);
static_assert(is_same
<
decltype(t),
std::tuple<int&, const int&, int>
>{}, "");
// Ok, modifies lr:
std::get<0>(t) = 10;
// Compile-time error, intended:
// std::get<1>(t) = 20;
// Ok, 5 was moved into the tuple:
std::get<2>(t) = 30;
Example incomplete implementation:
template<typename... Ts>
auto make_subpack_tuple(Ts&&... xs)
{
return std::tuple
<
some_type_trait<decltype(xs)>...
>
(
std::forward<decltype(xs)>(xs)...
);
}
Does what I am trying to do make sense?
Is there a standard type-trait that can be used in place of some_type_trait? Or should I implement my own solution?
The solution for you will be
template<typename... Ts>
auto make_subpack_tuple(Ts&&... xs)
{
return std::tuple<Ts...>(std::forward<Ts>(xs)...);
}
According to template argument deduction rules, the parameter pack Ts... will contain only cv-qualified types and lvalues. The information in this question may be useful too.
I'd just like to chime in that I ran into this same not-really-a-problem ("I think I need to decay rvalue references and keep lvalue references untouched") while implementing an efficient version of Nick Athanasios's foldable Op<operation>. I had had this mess:
template<class Pack, class Op>
struct Foldable
{
mystery_trait_t<Pack> value;
const Op& op;
template<class RhsPack>
auto operator*(const Foldable<RhsPack, Op>& rhs) const {
return op(static_cast<std::decay_t<Pack>>(
(op.f)(std::move(value), std::move(rhs.value))
));
}
operator mystery_trait_t<Pack> () && {
return std::move(value);
}
};
template<class Pack>
auto NamedOperator::operator()(Pack&& value) const {
return Foldable<Pack, NamedOperator>(std::forward<Pack>(value), *this);
}
and (after puzzling for a bit, and then starting to ask a SO question, and finding this existing question/answer, and adding a static_assert to my implementation of mystery_trait_t to verify that it was never actually invoked with an rvalue reference type!) it turned out that all I actually needed was
template<class Pack, class Op>
struct Foldable
{
Pack value;
const Op& op;
template<class RhsPack>
auto operator*(const Foldable<RhsPack, Op>& rhs) const {
return op(
(op.f)(std::move(value), std::move(rhs.value))
);
}
operator Pack () && {
return std::move(value);
}
};
(See my whole code on Wandbox.)
This "answer" of mine doesn't contribute any new information, but I thought it would be useful to share, because it just goes to show that even if you think you're way deep in template metaprogramming and are sure you need this "conditional decay" behavior... you really don't need it!
There might be a corollary general rule that writing any_template<T&&> is always a code smell. In Vittorio's original question, he effectively did that twice, although both times it was hidden by decltype syntax:
some_type_trait<decltype(xs)>... // should have been `Ts...`
std::forward<decltype(xs)>(xs)... // could equally well be `std::forward<Ts>(xs)...`

Const and non-const functors

This seems like something that ought to be frequently asked and answered, but my search-fu has failed me.
I'm writing a function which I want to accept a generic callable object of some kind (including bare function, hand-rolled functor object, bind, or std::function) and then invoke it within the depths of an algorithm (ie. a lambda).
The function is currently declared like this:
template<typename T, typename F>
size_t do_something(const T& a, const F& f)
{
T internal_value(a);
// do some complicated things
// loop {
// loop {
f(static_cast<const T&>(internal_value), other_stuff);
// do some more things
// }
// }
return 42;
}
I'm accepting the functor by reference because I want to guarantee that it does not get copied on entry to the function, and thus the same instance of the object is actually called. And it's a const reference because this is the only way to accept temporary objects (which are common when using hand-rolled functors or bind).
But this requires that the functor implement operator() as const. I don't want to require that; I want it to be able to accept both.
I know I can declare two copies of this method, one that accepts it as const and one as non-const, in order to cover both cases. But I don't want to do that as the comments are hiding quite a lot of code that I don't want to duplicate (including some loop constructs, so I can't extract them to a secondary method without just moving the problem).
I also know I could probably cheat and const_cast the functor to non-const before I invoke it, but this feels potentially dangerous (and in particular would invoke the wrong method if the functor intentionally implements both const and non-const call operators).
I've considered accepting the functor as a std::function/boost::function, but this feels like a heavy solution to what ought to be a simple problem. (Especially in the case where the functor is supposed to do nothing.)
Is there a "right" way to satisfy these requirements short of duplicating the algorithm?
[Note: I would prefer a solution that does not require C++11, although I am interested in C++11 answers too, as I'm using similar constructs in projects for both languages.]
Have you tried a forwarding layer, to force inference of the qualifier? Let the compiler do the algorithm duplication, through the normal template instantiation mechanism.
template<typename T, typename F>
size_t do_something_impl(const T& a, F& f)
{
T internal_value(a);
const T& c_iv = interval_value;
// do some complicated things
// loop {
// loop {
f(c_iv, other_stuff);
// do some more things
// }
// }
return 42;
}
template<typename T, typename F>
size_t do_something(const T& a, F& f)
{
return do_something_impl<T,F>(a, f);
}
template<typename T, typename F>
size_t do_something(const T& a, const F& f)
{
return do_something_impl<T,const F>(a, f);
}
Demo: http://ideone.com/owj6oB
The wrapper should be completely inlined and have no runtime cost at all, except for the fact that you might end up with more template instantiations (and therefore larger code size), though that will only happen when for types with no operator()() const where both const (or temporary) and non-const functors get passed.
Answer for new relaxed requirements.
In commentary on another answer the OP has clarified/changed the requirements to…
“I'm ok with requiring that if the functor is passed in as a temporary
then it must have an operator() const. I just don't want to limit it
to that, such that if a functor is not passed in as a temporary (and
also not a const non-temporary, of course) then it is allowed to have
a non-const operator(), and this will be called”
This is then not a problem at all: just provide an overload that accepts a temporary.
There are several ways of distinguishing the original basic implementation, e.g. in C++11 an extra default template argument, and in C++03 an extra defaulted ordinary function argument.
But the most clear is IMHO to just give it a different name and then provide an overloaded wrapper:
template<typename T, typename F>
size_t do_something_impl( T const& a, F& f)
{
T internal_value(a);
// do some complicated things
// loop {
// loop {
f(static_cast<const T&>(internal_value), other_stuff);
// do some more things
// }
// }
return 42;
}
template<typename T, typename F>
size_t do_something( T const& a, F const& f)
{ return do_something_impl( a, f ); }
template<typename T, typename F>
size_t do_something( T const& a, F& f)
{ return do_something_impl( a, f ); }
Note: there's no need to specify the do_something_impl instantiation explicitly, since it's inferred from the lvalue arguments.
The main feature of this approach is that it supports simpler calls, at the cost of not supporting a temporary as argument when it has non-const operator().
Original answer:
Your main goal is to avoid copying of the functor, and to accept a temporary as actual argument.
In C++11 you can just use an rvalue reference, &&
For C++03 the problem is a temporary functor instance as actual argument, where that functor has non-const operator().
One solution is to pass the burden to the client code programmer, e.g.
require the actual argument to be an lvalue, not a temporary, or
require explicit specification that the argument is a temporary, then take it as reference to const and use const_cast.
Example:
template<typename T, typename F>
size_t do_something( T const& a, F& f)
{
T internal_value(a);
// do some complicated things
// loop {
// loop {
f(static_cast<const T&>(internal_value), other_stuff);
// do some more things
// }
// }
return 42;
}
enum With_temp { with_temp };
template<typename T, typename F>
size_t do_something( T const& a, With_temp, F const& f )
{
return do_something( a, const_cast<F&>( f ) );
}
If it is desired to directly support temporaries of const type, to ease the client code programmer's life also for this rare case, then one solution is to just add an additional overload:
enum With_const_temp { with_const_temp };
template<typename T, typename F>
size_t do_something( T const& a, With_const_temp, F const& f )
{
return do_something( a, f );
}
Thanks to Steve Jessop and Ben Voigt for discussion about this case.
An alternative and much more general C++03 way is to provide the following two little functions:
template< class Type >
Type const& ref( Type const& v ) { return v; }
template< class Type >
Type& non_const_ref( Type const& v ) { return const_cast<T&>( v ); }
Then do_something, as given above in this answer, can be called like …
do_something( a, ref( MyFunctor() ) );
do_something( a, non_const_ref( MyFunctor() ) );
Why I didn't think of that immediately, in spite of having employed this solution for other things like string building: it's easy to create complexity, harder to simplify! :)

C++ template to cover const and non-const method

I have a problem with duplication of identical code for const and non-const versions. I can illustrate the problem with some code. Here are two sample visitors, one which modifies the visited objects and one which does not.
struct VisitorRead
{
template <class T>
void operator()(T &t) { std::cin >> t; }
};
struct VisitorWrite
{
template <class T>
void operator()(const T &t) { std::cout << t << "\n"; }
};
Now here is an aggregate object - this has just two data members but my actual code is much more complex:
struct Aggregate
{
int i;
double d;
template <class Visitor>
void operator()(Visitor &v)
{
v(i);
v(d);
}
template <class Visitor>
void operator()(Visitor &v) const
{
v(i);
v(d);
}
};
And a function to demonstrate the above:
static void test()
{
Aggregate a;
a(VisitorRead());
const Aggregate b(a);
b(VisitorWrite());
}
Now, the problem here is the duplication of Aggregate::operator() for const and non-const versions.
Is it somehow possible to avoid duplication of this code?
I have one solution which is this:
template <class Visitor, class Struct>
void visit(Visitor &v, Struct &s)
{
v(s.i);
v(s.i);
}
static void test2()
{
Aggregate a;
visit(VisitorRead(), a);
const Aggregate b(a);
visit(VisitorWrite(), b);
}
This means neither Aggregate::operator() is needed and there is no duplication. But I am not comfortable with the fact that visit() is generic with no mention of type Aggregate.
Is there a better way?
I tend to like simple solutions, so I would go for the free-function approach, possibly adding SFINAE to disable the function for types other than Aggregate:
template <typename Visitor, typename T>
typename std::enable_if< std::is_same<Aggregate,
typename std::remove_const<T>::type
>::value
>::type
visit( Visitor & v, T & s ) { // T can only be Aggregate or Aggregate const
v(s.i);
v(s.d);
}
Where enable_if, is_same and remove_const are actually simple to implement if you don't have a C++0x enabled compiler (or you can borrow them from boost type_traits)
EDIT: While writing the SFINAE approach I realized that there are quite a few problems in providing the plain templated (no SFINAE) solution in the OP, which include the fact that if you need to provide more than one visitable types, the different templates would collide (i.e. they would be as good a match as the others). By providing SFINAE you are actually providing the visit function only for the types that fulfill the condition, transforming the weird SFINAE into an equivalent to:
// pseudocode, [] to mark *optional*
template <typename Visitor>
void visit( Visitor & v, Aggregate [const] & s ) {
v( s.i );
v( s.d );
}
struct Aggregate
{
int i;
double d;
template <class Visitor>
void operator()(Visitor &v)
{
visit(this, v);
}
template <class Visitor>
void operator()(Visitor &v) const
{
visit(this, v);
}
private:
template<typename ThisType, typename Visitor>
static void visit(ThisType *self, Visitor &v) {
v(self->i);
v(self->d);
}
};
OK, so there's still some boilerplate, but no duplication of the code that depends on the actual members of the Aggregate. And unlike the const_cast approach advocated by (e.g.) Scott Meyers to avoid duplication in getters, the compiler will ensure the const-correctness of both public functions.
Since your ultimate implementations are not always identical, I don't think there's a real solution for your perceived "problem".
Let's think about this. We have to cater for the situations where Aggregate is either const or non-const. Surely we should not relax that (e.g. by providing only a non-const version).
Now, the const-version of the operator can only call visitors which take their argument by const-ref (or by value), while the non-constant version can call any visitor.
You might think that you can replace one of the two implementations by the other. To do so, you would always implement the const version in terms of the non-const one, never the other way around. Hypothetically:
void operator()(Visitor & v) { /* #1, real work */ }
void operator()(Visitor & v) const
{
const_cast<Aggregate *>(this)->operator()(v); // #2, delegate
}
But for this to make sense, line #2 requires that the operation is logically non-mutating. This is possible for example in the typical member-access operator, where you provide either a constant or a non-constant reference to some element. But in your situation, you cannot guarantee that the operator()(v) call is non-mutating on *this!
Therefore, your two functions are really rather different, even though they look formally similar. You cannot express one in terms of the other.
Maybe you can see this another way: Your two functions aren't actually the same. In pseudo-code, they are:
void operator()(Visitor & v) {
v( (Aggregate *)->i );
v( (Aggregate *)->d );
}
void operator()(Visitor & v) const {
v( (const Aggregate *)->i );
v( (const Aggregate *)->d );
}
Actually, coming to think of it, perhaps if you're willing to modify the signature a bit, something can be done:
template <bool C = false>
void visit(Visitor & v)
{
typedef typename std::conditional<C, const Aggregate *, Aggregate *>::type this_p;
v(const_cast<this_p>(this)->i);
v(const_cast<this_p>(this)->d);
}
void operator()(Visitor & v) { visit<>(v); }
void operator()(Visitor & v) const { const_cast<Aggregate *>(this)->visit<true>()(v); }
Normally with this type of thing, it's possibly better to use methods that make sense. For example, load() and save(). They say something specific about the operation that is to be carried out via the visitor. Typically both a const and non-const version is provided (for things like accessors anyway), so it only appears to be duplication, but could save you some headache debugging later down the line. If you really wanted a workaround (which I wouldn't advice), is to declare the method const, and all the members mutable.
Add visitor trait to tell whether it's modifying or not (const or non-const use).
This is used by STL iterators.
You could use const_cast and change VisitorRead's method signature so it also take's const T& as a parameter, but I think that is an ugly solution.
Another solution - require the Visitor class to have a metafunction that adds const when it applies:
template <class Visitor>
static void visit(Visitor &v, typename Visitor::ApplyConst<Aggregate>::Type &a)
{
v(a.i);
v(a.d);
}

Passing temporaries as non-const references in C++

I have the following piece of code, as an example dec_proxy attempts to reverse the effects of the increment operator upon the type that is executed in a complex function call foo - which btw I cannot change the interface of.
#include <iostream>
template<typename T>
class dec_proxy
{
public:
dec_proxy(T& t)
:t_(t)
{}
dec_proxy<T>& operator++()
{
--t_;
return *this;
}
private:
T& t_;
};
template<typename T, typename S, typename R>
void foo(T& t, S& s, R& r)
{
++t;
++s;
++r;
}
int main()
{
int i = 0;
double j = 0;
short k = 0;
dec_proxy<int> dp1(i);
dec_proxy<double> dp2(j);
dec_proxy<short> dp3(k);
foo(dp1,dp2,dp3);
//foo(dec_proxy<int>(i), <---- Gives an error
// dec_proxy<double>(j), <---- Gives an error
// dec_proxy<short>(k)); <---- Gives an error
std::cout << "i=" << i << std::endl;
return 0;
}
The problem is that for the various types I'd like to use dec_proxy I currently require creating a specialized instance of dec_proxy - it seems like a very messy and limited approach.
My question is: What is the correct way to pass such short-lived temporaries as non-const reference parameters?
Taking Stephen's advice, you should look at the answer to How come a non-const reference cannot bind to a temporary object? and simply add a member function that returns a reference dec_proxy, e.g.:
dec_proxy &ref() { return *this; }
and call foo:
foo(
dec_proxy<int>(i).ref(),
dec_proxy<double>(j).ref(),
dec_proxy<short>(k).ref());
I'm pretty sure that compiles.
Thanks to MSN, the solution:
I don't think it is correct by adding the function template template<typename T> dec_proxy_impl<T>& dec_proxy(T&t).
What it did is just cheating compiler. It will result in runtime error. The function foo requires the lvaue or lvalue reference. But template<typename T> dec_proxy_impl<T>& dec_proxy(T&t) doesn't return a valid lvalue reference. In the implementation, it creates a temporary object, and returns it. After the function call finishes, the temporary object will be destroyed. So the value reference passed into the function foo is wrong. Actually the referenced object has already been destroyed. The ++t;++s;++r are trying to access the invalid objects. The behavior is undefined.
The solution from MSN is correct. The life time of the object dec_proxy<int>(i) is from its declaration to the end of the function call. It makes sure the parameter in the function foo is valid.
What you try to do is to pass a rvalue (your new dec_facade<int>(i)) as an lvalue reference, which explains why it doesn't work.
If you compiler support it, you can use rvalue references, using && type modifier :
(Support for rvalue reference could be enabled by switching on C++0x or C++11 [partial] support)
template<typename T>
void foo(T& t)
{
++t;
}
template<typename T>
void foo(T&& t)
{
++t;
}
But that only one part of the problem. What you try to do, is to pre-increment a temporary value! That's non-sense, as it won't live after that call. Your object will be increment, then destroyed.
One other solution would be to remove the & from your function definition, which would permit it to accept any parameter. But that's perhaps not what you want.

macro solution for duplicate, const and non-const, getters?

Can this solution be turned into a macro so that I call something along the lines of:
CALL_CONST_FUNC(objToReturn, thisPtr)->SomeConstFunc();
For functions that return a value and another for functions that don't. My macro token skills are not that great so I thought maybe someone here can come up with one (or tell me that it is not possible). Ultimately the goal is to avoid writing the ugly one-liner and replace it with something that is easy on the eyes and not error prone.
If a function doesn't return a value (reference or pointer), do you need const overloads in the first place? It seems that the only reason to have two is to get a const or non-const reference out of the class. Otherwise the const version alone should be enough.
As to making the idiom sweeter, how about a few template helpers instead to do type deduction for you:
template <class T>
const T& add_const(T& t) { return t; }
template <class T>
T& remove_const(const T& t) { return const_cast<T&>(t); }
class Foo
{
int foo;
public:
const int& get() const
{
//non-trivial work
return foo;
}
int& get()
{
return remove_const(add_const(*this).get());
}
};
The benefit is greater if the type names are longer.