template copy constructor in boost::any - c++

template copy constructor in boost::any
I am confused with these codes in any.hpp of boost.
template<typename ValueType>
any(const ValueType & value)
: content(new holder<
BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type
>(value))
{
}
any(const any & other)
: content(other.content ? other.content->clone() : 0)
{
}
It's clear that for the sencod copy-constructor is useful when I need a new any object from another object.
But when the first copy-constucted will be executed?

The template constructor (which is not a copy constructor) constructs a boost::any from a const reference to some object of ValueType. The copy constructor makes a copy of an any (performing a polymorphic clone of the object within).
Here is an example of when the first form will be selected:
std::string s = "Hello, World";
boost::any a(s); // template constructor selected here
boost::any b(a); // copy constructor selected here.

Related

Should you provide the copy constructor or the move constructor with a default argument?

Suppose you have the following class:
template<typename T>
class A
{
...
A (T const &t)
{
...
}
A (T &&t) noexcept
{
...
}
};
Now suppose I want to provide a default argument to one of these (i.e., = T{}). Which is more efficient/consistent to default, the copy or the move? Does it even matter? My gut says it doesn't matter performance wise, which leads me to think it would be more consistent to default the copy since you should not bind a temporary to an r-value.
Thoughts?
Those are not copy / move constructors, so you don't have to use a reference at all.
Assuming you have distinguished those cases to elide copying t if you can, just have one construtor
template<typename T>
class A
{
...
/* explicit ? */ A (T t = {})
{
...
}
};

c++ custom container pass {} list

I am basically remaking the set container and I am wondering how I pass a brace-enclosed initializer list to the container.
mySet<int> myset = {"test", "test 2"};
I tried to overload the operator= to take a list as a parameter.
Despite the presence of the = here, this is constructing a set, so what you need is a constructor (that takes an std::initializer_list as its parameter).
template<class T>
class myset {
public:
// ...
mySet(std::initializer_list<T> init) {
for (T const &t : init)
insert(t);
}
};
You need to implement a constructor which take a std::initializer_list as its parameter, such as:
template <class T>
class mySet {
public:
mySet(std::initializer_list<T> l) {
// ...
}
};
Define a constructor that takes a std::initializer_list as a parameter, like
mySet(std::initializer_list<T> args){/*...*/}
operator= is invoked only on assignments, not on copy initialization (your case). In this latter case the constructor is invoked on the rhs, followed by a copy (or move), which is usually elided, but nevertheless the copy or move ctors must be accessible.

Copy Constructor invoked instead of assignment operator

Consider the following self contained Code.
#include <iostream>
template<typename Ty>
class Foo {
private:
Ty m_data;
public:
Foo() :m_data() {}
Foo(Ty data) :m_data(data) {}
template<typename U>
Foo& operator=(Foo<U> rv)
{
m_data = rv.m_data;
return *this;
}
private:
Foo(Foo&);
Foo& operator=(Foo&);
};
int main()
{
Foo<int> na(10);
Foo<int> nb;
nb = Foo<int>(10); // (1)
Foo<int>(10); // (2)
}
My understanding is statement (1) is an assignment rather than a Copy COnstructor. Yet, when compiling (VC++ and G++), the Error Message states, it tries to match a Copy Constructor which was declared private.
1>Source.cpp(23): error C2248: 'Foo<int>::Foo' : cannot access private member declared in class 'Foo<int>'
1> Source.cpp(16) : see declaration of 'Foo<int>::Foo'
My question is, why does it try to search for a Copy Constructor instead of an assignment.
Note, I know it is the assignment that is failing because (2) compiles fine without any error.
Your assignment operator takes its parameter by value, which requires making a copy. That copy may (or may not) be elided - but the copy constructor still needs to be available and accessible, even if not called.
There are two issues:
Your private assignment operator Foo& operator=(Foo&); takes a non-const lvalue reference. That means it cannot be selected as an overload in nb = Foo<int>(10);, because the RHS is an rvalue
That leads to your template assignment operator being selected. But that takes its argument by value, requiring a copy or move copy constructor.
If you fix 1. to take a const reference, gcc gives the following error:
error: 'Foo& Foo::operator=(const Foo&) [with Ty = int]' is private
If you fix 2. so that the template assignment operator takes a const reference, the code compiles without errors.
Your assignment operator passes argument by value, so it uses copy ctor:
template<typename U>
Foo& operator=(Foo<U> rv)
Possible solution to pass it by const refernce:
template<typename U>
Foo& operator=(const Foo<U> &rv)
A private version
private:
Foo(Foo&);
Foo& operator=(Foo&);
cannot be called because it takes non-const lvalue reference so
Foo& operator=(Foo<U> rv)
this version is called but it takes parameter by value and copy constructor has to be invoked.

Can std::function be move-constructed from rvalue reference to a temporary functor object?

I have an untemplated functor object that I'm trying to store as a std::function inside another object. This object is really heavyweight, so it's marked as uncopyable, but it does have a move constructor. However, trying to construct a std::function, or assign it, from a temporary constructor fails.
Here is a minimal example to provoke the error.
// pretend this is a really heavyweight functor that can't be copied.
struct ExampleTest
{
int x;
int operator()(void) const {return x*2;}
ExampleTest( ) :x(0){}
ExampleTest( int a ) :x(a){}
// allow move
ExampleTest( ExampleTest &&other ) :x(other.x) {};
private: // disallow copy, assignment
ExampleTest( const ExampleTest &other );
void operator=( const ExampleTest &other );
};
// this sometimes stores really big functors and other times stores tiny lambdas.
struct ExampleContainer
{
ExampleContainer( int );
std::function<int(void)> funct;
};
/******** ERROR:
Compiler error: 'ExampleTest::ExampleTest' : cannot access private member
declared in class 'ExampleTest'
******************/
ExampleContainer::ExampleContainer( int x )
: funct( ExampleTest( x ) )
{}
/******** ERROR:
Compiler error: 'ExampleTest::ExampleTest' : cannot access private member
declared in class 'ExampleTest'
******************/
int SetExample( ExampleContainer *container )
{
container->funct = ExampleTest();
return container->funct();
}
In an even simpler construction, where I'm just making a local function, I also get the error:
int ContrivedExample( )
{
// extra parens to sidestep most vexing parse
std::function<int()> zug( (ExampleTest()) );
/*** ERROR: 'ExampleTest::ExampleTest' : cannot access private member
declared in class 'ExampleTest' */
int troz = zug( ) ;
return troz;
}
So far as I can tell, in all of these cases, a temporary ExampleTest ought to be passed to the function constructor as an rvalue. Yet the compiler wants to copy them.
What gives? Is it possible to pass uncopyable (but move-copyable) functor objects to a std::function constructor? There are workarounds with pointers and so on, but I want to understand what is going on here.
The specific errors above are from Visual Studio 2012 with the CTP C++11 patch. GCC 4.8 and Clang 3 also fall down, with their own error messages.
This object is really heavyweight, so it's marked as uncopyable, but it does have a move constructor.
If a functor is non-copyable, it does not meet the necessary requirements for being used with std::function. Paragraph 20.8.11.2.1/7 of the C++11 Standard specifies:
template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);
7 Requires: F shall be CopyConstructible. f shall be Callable (20.8.11.2) for argument types ArgTypes
and return type R. The copy constructor and destructor of A shall not throw exceptions.
std::function can be move-constructed from rvalue of a functor object. And most implementations do that.
The "my target must be copy-constructable" requirement of std::function is due to its own requirement of being copy-constructable. std::function's type is defined only by its target's signature(eg: void(int)) and std::function itself is defined by the standard to be copy-constructable. So when you copy-construct a std::function, it needs to call the copy-ctor of the its target(the underlying functor). So it requires its target having one. It has no other choices.
Having the requirement that the target being copy-constructable, the standard does not say that the implementations should copy, instead of move, when you construct a std::function from a rvalue callable object. The implemention will probably only call the move-ctor of your callable object.
More detailed additional information with examples and tests:
For example in gcc(MSVC is similar) implementation for the ctor of std::function from any callable object:
template<typename _Res, typename... _ArgTypes>
template<typename _Functor, typename>
function<_Res(_ArgTypes...)>::
function(_Functor __f)
: _Function_base()
{
typedef _Function_handler<_Signature_type, _Functor> _My_handler;
// don't need to care about details below, but when it uses __f, it
// either uses std::move, or passes it by references
if (_My_handler::_M_not_empty_function(__f))
{
_My_handler::_M_init_functor(_M_functor, std::move(__f));
_M_invoker = &_My_handler::_M_invoke;
_M_manager = &_My_handler::_M_manager;
}
}
passing by value of the argument of "_Functor __f" will use its move constructor if it has one, and it will use its copy constructor if it does not have a move ctor. As the following test program can demonstrate:
int main(){
using namespace std;
struct TFunctor
{
TFunctor() = default;
TFunctor(const TFunctor&) { cout << "cp ctor called" << endl; }
TFunctor(TFunctor&&) { cout << "mv ctor called" << endl; };
void operator()(){}
};
{ //!!!!COPY CTOR of TFunctor is NEVER called in this scope
TFunctor myFunctor;
//TFunctor move ctor called here
function<void()> myStdFuncTemp{ std::move(myFunctor) };
function<void()> myStdFunc{ move(myStdFuncTemp) };
}
{ //TFunctor copy ctor is called twice in this scope
TFunctor myFunctor;
//TFunctor copy ctor called once here
function<void()> myStdFuncTemp{ myFunctor };
//TFunctor copy ctor called once here
function<void()> myStdFunc{ myStdFuncTemp };
}
}
Finally, you could make a unstd::function_only_movable which has almost everything the same with std::function but deletes its own copy ctor so it does not need to require the target callable object to have one copy ctor. You also need to only construct it from rvalue of callable objects.

Finding typeid of a template parameter

The print statement in the constructor's definition doesn't get printed, isn't the constructor calling correct in main? I know I am missing some point here, please point out.
#include <iostream>
#include <typeinfo>
template <typename T> class List
{
public:
template <typename T2> List (List<T2> const&);
};
template <typename T> template <typename T2> List <T> :: List (List <T2> const&)
{
std :: cout << "\nType name:" << typeid (T2).name();
}
int main ()
{
List <int> kk (List <int>);
return 0;
}
There are a couple of things wrong in your code that you might not be aware of.
List<int> kk( List<int> );
That line is not a variable definition, but rather the declaration of a function that takes a List<int> as argument and returns a List<int>, so that effectively will not call any constructor. That is know as the most-vexing-parse (you can look at different versions of it by searching in SO, or in the C++ FAQ lite)
The second issue is that you cannot possibly create any instance of the an instantiated type of List, the reason being is that the only constructor that you are providing is a templated constructor that takes a second List<U> as argument. That effectively disables the default constructor, so the only way of creating a List<T> is by already having a List<U>, and that is not possible. You can add the default constructor back:
template <typename T>
class List {
public:
List() {}
template <typename U>
List( List<U> const & ) {} // prefer const& as that will avoid unnecessary copying
};
And now you can write:
List<int> l = List<int>(); // this will call List<int>::List( List<int> const & )
And yet, that will still not call the constructor you want. The reason is a little obscure, but when copy constructing an element of a template, the compiler will not use a templated constructor. In the code above, it will implicitly define a copy constructor by doing member-wise copy constructor of the methods and call that generated constructor. That means that in most occasions where you want to provide a templated constructor you want to also provide a non-templated copy constructor.
To actually call that constructor you would have to provide a different type:
List<int> l = List<double>();
Since the types actually differ, the compiler cannot copy construct, will find that the provided templated constructor is the best overload candidate and call it.
As well as the "most vexing parse" identified by David:
you need to have at least one more constructor to create the original List object to be passed to the copy constructor,
you need to vary the parameter type in order to have the templated copy constructor invoked: as is you'll match the implicitly declared List(const List&) copy constructor instead.
So:
#include <iostream>
template <typename T>
struct X
{
X() { std::cout << "X()\n"; }
// implicitly like this anyway...
// X(const X& rhs) { std::cout << "X(X&)\n"; }
template <typename U>
X(const U& u) { std::cout << "U\n"; }
};
int main()
{
X<int> x;
X<int> y(x);
}
What are you trying to do with this statement:
List <int> kk (List <int>);
(It actually declares a function, and can't be anything but
a function declaration.)
In order to see output from the copy constructor, you've got to
invoke the copy constructor somehow. Which means having an
object to copy. Which isn't possible with the code you've
given: since you've explicitly declared a constructor, the
compiler will not provide a default constructor, and you have no
other constructor with which to create an object. So you have
no way of creating anything to copy. If you add a
List() {}
to the class, and write:
List<int> kk((List<int>());
, you might get something, but the compiler is allowed to elide
the copy here, so more likely there will be no output. Try:
List<int> a;
List<int> b(a);
Or just put your output in the default constructor.