The copy constructor and overloaded '=' operator are not being called when assigned with result of sum of two class objects. There are working properly when initialized and assigned with single object. the error says "no match for ‘operator=’ (operand types are ‘comp’ and ‘comp’)". Important code snippets are
class comp
{
int a,b;
public:
comp()
{
a=b=1;
}
comp(int,int);
comp(comp &);
comp operator+(comp &);
operator int();
void show()
{
cout<<"a= "<<a<<"b= "<<b<<endl;
}
comp& operator=(comp &);
friend ostream &operator<<(ostream &out, comp &c);
};
comp::comp(comp & c)//copy constructor
{
a=c.a,b=c.b;
cout<<"copy constructor called"<<endl;
}
comp comp::operator+(comp & c1)// overloaded '+' opreator
{
comp c;
c.a=a+c1.a;
c.b=b+c1.b;
return c;
}
comp & comp::operator =(comp & c)// I tried with return type as void also
{
cout<<"in operator ="<<endl;
a=c.a,b=c.b;
return *this;
}
int main()
{
comp c1,c2(2,3),c3;
c3=c2+c1;
cout<<c3;
comp c4=c3+c1;
cout<<c4;
int i=c4;
cout<<i;
return 0;
}
Lets take this line
comp c4=c3+c1;
The c3+c1 operation returns a temporary object. However, non-constant references can't bind to temporary objects, and your copy-constructor takes its argument as a non-constant reference.
The fix is simple, change the copy-constructor and copy-assignment operator to take their arguments as constant references instead, e.g.
comp(const comp& c);
Note that using a non-constant reference argument in e.g. a copy-constructor still makes it possible to use it, you just have to pass actual non-temporary objects to it, like
comp c1;
comp c2 = c1; // Should work with non-constant reference
By default some copy operations are optimized. To make sure that no copy optimization is used you should use proper compiler flag. For gcc try to use: -no-eligible-constructors
Related
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 ]
This is part of an assignment, I am stuck at this instruction:
Sort your randomly generated pool of schedules.
Use std::stable_sort,
passing in an object of type schedule_compare as the custom comparison
operator.
UPDATE: I was checking cppreference stable_srot(), see method definition below:
void stable_sort ( RandomAccessIterator first, RandomAccessIterator
last,Compare comp );
, and it seems from what I understood is that you can only pass functions to the last argument (Compare comp) of the stable_sort() i.e:
However, in the instructions, it says that you need to pass an object of type schedule_compare. How is this possible ?
This is my code below:
struct schedule_compare
{
explicit schedule_compare(runtime_matrix const& m)
: matrix_{m} { }
bool operator()(schedule const& obj1, schedule const& obj2) {
if (obj1.score > obj2.score)
return true;
else
return false;
}
private:
runtime_matrix const& matrix_;
};
auto populate_gene_pool(runtime_matrix const& matrix,
size_t const pool_size, random_generator& gen)
{
std::vector<schedule> v_schedule;
v_schedule.reserve(pool_size);
std::uniform_int_distribution<size_t> dis(0, matrix.machines() - 1);
// 4. Sort your randomly generated pool of schedules. Use
// std::stable_sort, passing in an object of type
// schedule_compare as the custom comparison operator.
std::stable_sort(begin(v_schedule), end(v_schedule), ???)
return; v_schedule;
}
For algorithm functions that accepts a "function" (like std::stable_sort) you can pass anything that can be called as a function.
For example a pointer to a global, namespace or static member function. Or you can pass a function-like object instance (i.e. an instance of a class that has a function call operator), also known as a functor object.
This is simply done by creating a temporary object, and passing it to the std::stable_sort (in your case):
std::stable_sort(begin(v_schedule), end(v_schedule), schedule_compare(matrix));
Since the schedule_compare structure have a function call operator (the operator() member function) it can generally be treated like any other function, including being "called".
Consider this:
int func1( int i );
int func2( int i );
Conditional operator can be used like that:
int res = (cond)?func1(4):func2(4);
Or, if both may use the same parameter:
int res = ((cond)?func1:func2)(4);
Now, what about member functions of a class:
class T
{
public:
T( int i ) : i(i) {}
int memfunc1() { return 1*i; }
int memfunc2() { return 2*i; }
private:
int i;
};
I tried this, but it does not work:
T t(4);
int res2 = t.((cond)?memfunc1:memfunc2)();
...tried other syntax too ((t.*((cond)?&(T::memfunc1):&(T::memfunc2)))()) with no success...
Is that doable and then what would be the good syntax? One line code answer are preferable (using a temporary auto variable to store pointer to function would be too easy...;-)
§ 5.3.1 [expr.unary.op]/p4:
A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed
in parentheses. [ Note: that is, the expression &(qualified-id), where the qualified-id is enclosed in
parentheses, does not form an expression of type “pointer to member.” Neither does qualified-id, because
there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to
member function” as there is from an lvalue of function type to the type “pointer to function” (4.3). Nor is
&unqualified-id a pointer to member, even within the scope of the unqualified-id’s class. — end note ]
If it still doesn't help, you can uncover the correct syntax below:
(t.*(cond ? &T::memfunc1 : &T::memfunc2))()
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.
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).