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.
Related
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 = {})
{
...
}
};
This code has a templated class. The default constructor appears to call itself recursively. How can it do that? I don't understand this code. Maybe if I would be given an example without templates, just POD types, things would be clearer. I haven't encountered this construct before in C++ programming. I think that I don't understand both the constructor and the templates.
template <typename T>
class Simple {
public:
Simple(T value = T()); // What's this?
T value();
void set_value(T value);
private:
T value_;
};
template<typename T>
Simple<T>::Simple(T value) {
value_ = value;
}
template<typename T>
T Simple<T>::value() {
return value_;
}
template<typename T>
void Simple<T>::set_value(T value) {
value_ = value;
}
My question is:
What does T value = T() do?
Class Simple has a variable value of type T (Templated).
The constructor which you are pointing is a default constructor. When no parameter is supplied while creating Simple object. Then default constructor will instantiate the value object to the default constructor of T.
Either , Simple(T value = T()) is a default constructor which is instantiating value to default constructor of typed element.
Example :-
if T is String.
Simple (String value = String())
so value is now initialized to default of String().
It is just a default value as void foo(int i = 42);, there are no recursion.
foo(); is equivalent to foo(42);.
In the same way, with Simple(T value = T());
Simple<int> s{}; would be equivalent to Simple<int> s{0}; and
Simple<std::string> s{}; would be equivalent to Simple<std::string> s{std::string{}}; (empty string).
T() would call the default constructor of given T (int and std::string in my examples).
I am trying to insert an instance of a templated class that does not have a copy constructor into a map. The code below does not work, because at the emplace function the compiler wants to call the copy constructor. I do not understand why, because I understood from the C++ reference that emplace does not move or copy:
Careful use of emplace allows the new element to be constructed while
avoiding unnecessary copy or move operations.
This is my code:
#include <map>
#include <string>
template<typename T> class Class_a
{
public:
Class_a(T t1, T t2) : t1_(t1), t2_(t2) {}
~Class_a() {}
Class_a(const Class_a&) = delete;
Class_a& operator=(const Class_a&) = delete;
Class_a(Class_a&&) = delete;
private:
const T t1_;
const T t2_;
};
template<typename T>
using Class_a_map = std::map<std::string, Class_a<T>>;
int main()
{
Class_a_map<double> class_a_map;
std::string name = "test";
double number1 = 42;
double number2 = 43;
class_a_map.emplace(name, Class_a<double>(number1, number2));
return 0;
}
You can use std::piecewise_construct and std::forward_as_tuple to create your objects in place.
class_a_map.emplace(
std::piecewise_construct,
std::forward_as_tuple(name),
std::forward_as_tuple(number1, number2)
);
live wandbox example
std::map::emplace perfectly forwards a bunch of arguments to the underlying std::pair used for key/value storage. std::pair::pair has an overload that takes an std::piecewise_construct_t as its first argument and then two std::tuple instances: the first one will be used to construct .first in place, the second one will be used to construct .second in place.
From cppreference, regarding std::pair's piecewise constructor:
Forwards the elements of first_args to the constructor of first and forwards the elements of second_args to the constructor of second. This is the only non-default constructor that can be used to create a pair of non-copyable non-movable types.
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.
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.