Additional move constructor in pass by value function - c++11

I have a simple struct, that has all constructors defined.
It has an int variable, each constructor and assign operator prints address of *this, current value of int and a new value of int.
Move and copy assign operators and constructors also print adress of passed value.
#include <iostream>
struct X
{
int val;
void out(const std::string& s, int nv, const X* from = nullptr)
{
std::cout<<this<<"->"<<s<<": "<<val<<" ("<<nv<<")";
if (from)
std::cout<<", from: ["<<from<<"]";
std::cout<<"\n";
}
X(){out("simple ctor X()",0); val = 0;}
X(int v){out("int ctor X(int)", v);val = v; }
X(const X& x){out("copy ctor X(X&)", x.val, &x);val = x.val; };
X&operator = (const X& x){out("copy X::operator=()", x.val, &x); val = x.val; return *this;}
~X(){out("dtor ~X", 0);}
X&operator = (X&& x){out("move X::operator(&&)", x.val, &x); val = x.val; return *this;}
X(X&& x){out("move ctor X(&&x)", x.val, &x);val = x.val;}
};
X copy(X a){return a;}
int main(int argc, const char * argv[]) {
X loc{4};
X loc2;
std::cout<<"before copy\n";
loc2 = copy(loc);
std::cout<<"copy finish\n";
}
output:
0xffdf7278->int ctor X(int): 134523184 (4)
0xffdf727c->simple ctor X(): 134514433 (0)
before copy
0xffdf7280->copy ctor X(X&): 1433459488 (4), from: [0xffdf7278]
0xffdf7284->move ctor X(&&x): 1433437824 (4), from: [0xffdf7280]
0xffdf727c->move X::operator(&&): 0 (4), from: [0xffdf7284]
0xffdf7284->dtor ~X: 4 (0)
0xffdf7280->dtor ~X: 4 (0)
copy finish
0xffdf727c->dtor ~X: 4 (0)
0xffdf7278->dtor ~X: 4 (0)
What's the purpose of creating an additional object with (in this example) address 0xffdf7284?

If you look at the copy elision rules from cppreference.com, you can notice that there are two case where the compilers are required to omit the copy- and move- constructors of class objects even if copy/move constructor and the destructor have observable side-effects (which yours do, due to the printouts). The first is clearly irrelevant to this case. The second is
In a function call, if the operand of a return statement is a prvalue and the return type of the function is the same as the type of that prvalue.
With the example given of:
T f() { return T{}; }
T x = f();
This seems more relevant, however, note that in your case, the operand of the return statement is not a prvalue. So in this case, no mandatory elision applies.
The set of steps, when callingloc2 = copy(loc);, is as follows:
a is copy-constructed from loc.
The return value of the function is move-constructed from a.
loc2 is move-assigned from the return value.
Logically, a person could look at the code and deduce that fewer operations need to be done (in particular, when looking at copy, it's obvious that, logically, an assignment from loc to loc2 is enough), but the compiler doesn't know that the purpose of your code isn't to generate the side effects (the printouts), and it is not breaking any rules here.

Related

disable assign integer to string c++

std::string (std::basic_string) have assignment operator for 'char' type.
But, for this reason, std::string may assign any integral types.
See little example.
#include <string>
enum MyEnum{ Va = 0, Vb = 2, Vc = 4 };
int main(){
std::string s;
s = 'a'; // (1) OK - logical.
s = Vc; // (2) Ops. Compiled without any warnings.
s = true; // (3) Ops....
s = 23; // (4) Ops...
}
Q: How disable (or add warning ) (2, 3, 4) situations ??
There is a related Question
Given the constraints of C++03 and GCC 4.8 as in the tags, I could not get -Wconversion to do anything useful (and in GCC 7 it doesn't even generate the warnings for me despite telling it that I'm using --std=c++03).
As such, there's a good practical solution that requires only minimal change at your calling site:
Proxy the assignment via a class object that wraps your string and that allows assignment from char but disallows it from int:
#include <string>
enum MyEnum{ Va = 0, Vb = 2, Vc = 4 };
struct string_wr {
string_wr (std::string& s) : val(s) {}
operator std::string& () const { return val; }
// we explicitly allow assigning chars.
string_wr& operator= (char) { return *this; }
// ww explicitly disable assigning ints by making the operator unreachable.
private:
string_wr& operator= (int);
private:
std::string& val;
};
int main(){
std::string s;
s = 'a'; // (1) OK - logical.
s = Vc; // (2) Ops. Compiled without any warnings.
s = true; // (3) Ops....
s = 23; // (4) Ops...
string_wr m(s); // this is the only real change at the calling site
m = 'a'; // (1) OK - logical.
m = Vc; // (2) Should fail with "assignment is private" kind of error.
m = true; // (3) Should fail...
m = 23; // (4) Should fail...
}
However, if your final goal is to specifically get warnings or errors when using std::string, your best option in C++03 is to patch the <string> header to add the private int-assignment operator shown in the class above. But that means patching a system header and the procedure and results will be dependant on your compiler version (and will have to be repeated in each installation and compiler version).

C++11: Variadic template deduction logic

I have the following construct:
template <class... Args>
class some_class
{
public:
some_class() = default;
some_class(Args...) = delete;
~some_class() = default;
};
template<>
class some_class<void>
{
public:
some_class() = default;
~some_class() = default;
};
The reason for this is that I just want to allow the users to create objects using the default constructor, so for example:
some_class<int,float> b;
should work but
some_class<int,float> c(1,3.4);
should give me a compilation error.
At some point in time I also needed to create templates based on void hence, the specialization for void:
some_class<void> a;
But by mistake I have typed:
some_class<> d;
And suddenly my code stopped compiling and it gave me the error:
some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be
overloaded
some_class(Args...) = delete;
So here comes the question: I feel that I am wrong that I assume that some_class<> should be deduced to the void specialization... I just don't know why. Can please someone explain why some_class<> (ie: empty argument list) is different from some_class<void>? (A few lines from the standard will do :) )
https://ideone.com/o6u0D6
void is a type like any other (an incomplete type, to be precise). This means it can be used as a template argument for type template parameters normally. Taking your class template, these are all perfectly valid, and distinct, instantiations:
some_class<void>
some_class<void, void>
some_class<void, void, void>
some_class<void, char, void>
In the first case, the parameter pack Args has one element: void. In the second case, it has two elements: void and void. And so on.
This is quite different from the case some_class<>, in which case the parameter pack has zero elements. You can easily demonstrate this using sizeof...:
template <class... Pack>
struct Sizer
{
static constexpr size_t size = sizeof...(Pack);
};
int main()
{
std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl;
}
This will output:
0 1 2
[Live example]
I can't really think of a relevant part of the standard to quote. Perhaps this (C++11 [temp.variadic] 14.5.3/1):
A template parameter pack is a template parameter that accepts zero or more template arguments. [ Example:
template<class ... Types> struct Tuple { };
Tuple<> t0; // Types contains no arguments
Tuple<int> t1; // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
Tuple<0> error; // error: 0 is not a type
—end example ]

C++ lambdas passing

This is just theoretical question. When i execute this code:
#include <functional>
#include <cstdio>
struct A {
int value = 100;
A() {
printf("A\n");
}
A(const A& a) {
printf("copy A\n");
}
~A() {
printf("~A\n");
}
};
void function(std::function<int()> lambda) {
printf("%d\n", lambda());
}
int main()
{
A a;
auto lambda = [a]() -> int {
return a.value;
};
function(lambda);
return 0;
}
Output is this:
A
copy A
copy A
copy A
100
~A
~A
~A
~A
And my question is why struct A is copied 3 times, not 2?
One copy takes lambda capture, second takes passing argument to function and third takes what?
You will see the same number of copy operations, if you change your code as follows:
int main()
{
A a;
auto&& lambda = [a]() -> int {
return a.value;
};
std::function<int()>{lambda};
}
The first copy/move construction occurs when creating the lambda. The second and third copy/move constructions happen during construction of the std::function. According to N3690, the used constructor of std::function looks as follows:
template <class F> function(F);
That means, the passed argument will be copied/moved once when passing the argument to the constructor. Within the constructor, it will be copied/moved another time for type erasure.
If the constructor would use references instead (e.g. with perfect forwarding), you would only see two copy/move constructions. However, I don't know why it wasn't used in this case.
template <typename Arg> function(Arg&&);

Function taking lambda expression

For practicing purposes I wanted to create a function similar to std::transform():
template<class Tin, class Tout>
std::vector<Tout> map( const std::vector<Tin>& in,
const std::function<Tout(const Tin&)>& mapper ) {
std::vector<Tout> ret;
for( auto elem : in ) {
ret.push_back( mapper( in ) );
}
return ret;
}
and I intended it to use it as follows:
std::vector<Bar> bars /* = ... */;
std::vector<Foo> foos = map( bars, []( const Bar& bar ) { return bar.to_foo(); } );
However, I get undefined references for the function call. What is the correct signature for my map() function?
*Update: * Here's the actual error message (Bar = std::string, Foo = IPv6 (own class))
config.cc:98:61: error: no matching function for call to ‘map(const std::vector<IPv6>&, InterfaceConfig::set_ip6(const std::vector<IPv6>&)::<lambda(const IPv6&)>)’
config.cc:98:61: note: candidate is:
utils.h:38:31: note: template<class Tin, class Tout> std::vector<Tout> utils::map(const std::vector<Tin>&, const std::function<Tout(const Tin&)>&)
And here's the call:
std::vector strings = utils::map( ips,
[]( const IPv6& ip ) { return ip.to_string(); } );
There is two things in your code that will not work.
First, when passing a lambda function as argument, I suggest using Template. The standard library on Microsoft seems to use this method for std::for_each for example.
And :
When function template has a return type, which cannot be deduced from arguments, or when function template doesn't have any argument, the type cannot be deduced by the compiler. This function will require template type argument specification.
Take a look at this example :
template<class Tout, class Tin, class Fun>
// ^^^^^^^^^^^
// Note that I changed the order of the types
std::vector<Tout> map( const std::vector<Tin>& in,
Fun mapper ) {
// ^^^^^^^^^^
std::vector<Tout> ret;
for( auto elem : in ) {
ret.push_back( mapper( elem ) );
}
return ret;
}
int main()
{
std::vector<int> bars /* = ... */;
std::vector<float> foos = map<float>( bars, []( int ) { return 1.0f; } );
// ^^^^^^^ Specify the type Tout
system( "pause" );
return 0;
}
EDIT :
Like it is said in the comment, we can use decltype and std::decay to not have to explicitly specify the result of the function :
template<class Tin, class Fun> // no Tout
// ^^^^^^^^^^^
auto map( const std::vector<Tin>& in, Fun mapper )
//^^^^ ^^^^^^^^^^
-> std::vector<typename std::decay< decltype( mapper( in.front() ) )>::type > {
std::vector<typename std::decay< decltype( mapper( in.front() ) )>::type > ret;
for( auto elem : in ) {
ret.push_back( mapper( elem ) );
}
return ret;
}
int main()
{
std::vector<int> bars /* = ... */;
std::vector<float> foos = map( bars, []( int ) { return 1.0f; } );
// No specification
system( "pause" );
return 0;
}
Let's explain a little bit.
First we will use the late-specified return type syntax. It will allow us to use the parameter names in the return type specification. We start the line with auto and put the return type specification after the parameters using ->.
We will use decltype because the decltype type specifier yields the type of a specified expression. It will be very useful in our case. For example to get the type of the function we passed in parameters, it is just decltype( f( someArg ) ).
Let's state what do we want : The return type of the function should be a vector of the return type of the function passed in argument right ? So we can return std::vector< decltype( mapper( in.front() ) )> and that's it ! (Why the in.front() ? We have to pass a parameter to the function to have a valid expression.)
But here again, we have a problem : std::vector does not allow references. To be certain that it will not be a problem for us, we will use the std::decay meta-function who applies lvalue-to-rvalue, array-to-pointer, and function-to-pointer implicit conversions to the type T, removes cv-qualifiers, remove references, and defines the resulting type as the member typedef type.. That is, if the function returns something like const Foo& it will end in Foo.
The result of all of that : std::vector< typename std::decay< decltype( mapper( in.front() ) )>::type >.
You have to repeat this expression again at the beginning of the function to declare the variable you will return.
Some usefull references about that :
http://en.cppreference.com/w/cpp/types/decay
http://en.wikipedia.org/wiki/Decltype
http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html
http://msdn.microsoft.com/en-us/library/dd537655.aspx
It is not easy to explain, I hope my explanations are understandable.
There's no need to explicitly specify the result of map, it can be deduced. I'm also going to accept any range (something that provides begin and end), simply because doing so is trivial. I could make it even more generic and use the free begin and end versions, but that makes it even more complicated, so I won't.
template <typename Range, typename Func>
auto map(const Range& r, Func f)
-> std::vector<typename std::decay<decltype(f(*r.begin()))>::type> {
std::vector<typename std::decay<decltype(f(*r.begin()))>::type> result;
for (const auto& e : r) {
result.push_back(f(e));
}
// Alternatively:
//std::transform(r.begin(), r.end(), std::back_inserter(result), f);
return result;
}
This isn't exactly trivial code, so let me explain.
First, I use the late-specified return type syntax here: I start the function with auto and put the actual return type after the parameters, indicated with ->. This allows me to use parameter names in the return type specification, which is very useful in the decltype stuff I'm doing next.
So what do we actually want? We want a vector of whatever f returns when called with elements of r. What is that? Well, we can use decltype to find out. decltype(expr) gives you the type of expr. In this case, the expression is a call to f: decltype(f(arguments)). We have one argument: an element of the range. The only things a range gives us are begin() and end(), so let's use that: dereference begin() to get the actual value. The expression is now decltype(f(*r.begin())). Note that this is never actually evaluated, so it doesn't matter if the range is empty.
Ok, this gives us the return type of the function. But if we write std::vector<decltype(...)> that leaves us with a problem: the return type of the function could be a reference, but a vector of references is not valid. So we apply the std::decay metafunction to the return type, which removes references and cv-qualifiers on the referenced type, so if the function returns const Foo&, the result of std::decay is just Foo.
This leaves me with the final return type std::vector<typename std::decay<decltype(f(*r.begin()))>::type>.
And then you get to repeat the same thing to declare the actual variable holding the return value. Unfortunately, because there's no way to put type aliases at any reasonable point, you can't get rid of this.
Anyway, there was another problem with your original code, and that was declaring the loop variable as auto. If you call this map with a vector<Bar>, you end up with the loop
for (Bar b : in) { ... }
Notice how your loop variable is a value? This means that you copy every element of in to a local variable. If a Bar is expensive to copy, this is a serious performance issue. And if your transformation relies on the object identity of its argument (e.g. you return a pointer to a member), then your performance issue has become a correctness issue, because the resulting vector is full of dangling pointers. This is why you should use const auto& in the loop, or just use the std::transform algorithm internally, which gets this right.

Google Test and boost::variant

I wish to iterate over the types in my boost::variant within my unit test. This can be done as follows:
TEST_F (MyTest, testExucutedForIntsOnly)
{
typedef boost::variant<int, char, bool, double> var;
boost::mpl::for_each<SyntaxTree::Command::types>(function());
...
}
Where function is a functor. I simply want to ensure that a particular operation occurs differently for one type in the variant with respect to all others. However, I don't like that the test is now done in another function -- and what if I wish to access members for MyTest from the functor? It seems really messy.
Any suggestions on a better approach?
So, you want to call a function on a boost::variant that is type-dependent?
Try this:
template<typename T>
struct RunOnlyOnType_Helper
{
std::function<void(T)> func;
template<typename U>
void operator()( U unused ) {}
void operator()( T t ) { func(t); }
RunOnlyOnType_Helper(std::function<void(T)> func_):func(func_){}
};
template<typename T, typename Variant>
void RunOnlyOnType( Variant v, std::function< void(T) > func )
{
boost::apply_visitor( RunOnlyOnType_Helper<T>(func), v );
}
The idea is that RunOnlyOnType is a function that takes a variant and a functor on a particular type from the variant, and executes the functor if and only if the type of the variant matches the functor.
Then you can do this:
typedef boost::variant<int, char, bool, double> var;
var v(int(7)); // create a variant which is an int that has value 7
std::string bob = "you fool!\n";
RunOnlyOnType<int>( v, [&](int value)->void
{
// code goes here, and it can see variables from enclosing scope
// the value of v as an int is passed in as the argument value
std::cout << "V is an int with value " << value << " and bob says " << bob;
});
Is that what you want?
Disclaimer: I have never touched boost::variant before, the above has not been compiled, and this is based off of quickly reading the boost docs. In addition, the use of std::function above is sub-optimal (you should be able to use templated functors all the way down -- heck, you can probably extract the type T from the type signature of the functor).

Resources