I have a template class with a member whose type depends on the class' template argument. The class has a template constructor. How do I specialize the constructor for different cases of the class' template argument that determines the type of the said member. The different types in question are classes with different constructor signatures, and I'd like to call the member's constructor in the initializer list. Is there a workaround? I would like to avoid resorting to factory functions, because I don't want to rely on the move constructor of the member being cheap.
Edit: Here's a code example,
template <typename T, typename C>
struct foo {
T m;
C container;
using value_type = typename C::value_type;
template <typename... Args>
foo(Args&&... args)
: m(std::forward<Args>(args)...), container(/*different stuff here*/)
{}
};
My goal is to properly initialize the container
regardless of whether C
is a std::vector
or std::array
. If std::is_arithmetic<value_type>::value==true
, I want to initialize the container with all zeros (this is where the issue with different constructor signatures comes in). If std::is_arithmetic<value_type>::value==false
, I want to default initialize.
Your question is a little bit tricky to understand without an example. My understanding of it is that you want to specialize the constructor of a class template and construct it's member differently for different template arguments. If this isn't correct, let me know and I will adjust my answer.
Again without an example it's hard to know what you do and do not understand. But generally this is done the same way as you would specialize other methods. Declare all the specializations in your headers and implement them in your implementation file (unless they are partial specializations!). Remember to use
template<>
when specializing. Here is an example :Edit: In response to the edit to the question.
You cannot specialize a constructor in this case. The best solution is likely going to be to use a helper structs to do the actual initialization. You mentioned you want to initialize your containers with some number of 0 or default constructed elements
T
. However you didn't specify how large your containers should be. I've constructed an example to illustrate the solution of using helper structs using bogus container sizes.For the second part of your question, initializing to 0 to arithmetic types and default constructing for class types, the language already has a feature for this.
std::array specifically says this about it's construction.
Then aggregate initialization says this.
Finally value initialization says this.
This allow us to do this
std::array<T, 10> my_array{};
and have ten zeroed or default constructedT
s. We can also dostd::vector<T> my_vector(10, T{});
to get the same results (T{}
is value constructed`).Edit 2: Here is another solution that more adheres to the question's requirements using a [delegating constructor] and tag dispatching.