Reputation: 1147
I'm having two probably related problems with the code below.
It just defines two types Type1
and Type2
respectively and an "aggregate" type Types
that inherits from both of them.
My final goal is to make the commented constructor work to avoid having a temporary variable initialization. If I un-comment the code under Types
the compiler gives me an error:
error: class ‘Types<Args>’ does not have any field named ‘Args’
I tried to overcome the problem and came up with the code that compiles. However it does not give the expected output.
The expected output is
Type1:1
Type2:0
The actual output is
Type1:0
Type2:0
I do not know if two of my problems relate to each other. I guess that both of them arise from my possible lack of understanding parameter pack and inheritance hence I am posting both of them.
I appreciate if someone could shed some light on both of the problems.
struct Type1 {
Type1() = default;
template <typename T>
Type1() : init_{std::is_same<Type1, T>::value} {};
template <typename T>
Type1(T t) : init_{std::is_same<Type1, T>::value} {}
void Print() const { std::cout << "Type1:" << init_ << std::endl; }
bool init_{false};
};
struct Type2 {
Type2() = default;
template <typename T>
Type2() : init_{std::is_same<Type2, T>::value} {};
template <typename T>
Type2(T) : init_{std::is_same<Type2, T>::value} {}
void Print() const { std::cout << "Type2:" << init_ << std::endl; }
bool init_{false};
};
template <typename... Args>
class Types : public Args... {
public:
// error: class ‘Types<Args>’ does not have any field named ‘Args’
//
//template <typename T>
//Types()
// : Args<T>()... {}
template <typename T>
Types(T t)
: Args(t)... {}
};
int main() {
Types<Type1, Type2> types(Type1{});
static_cast<Type1>(types).Print();
static_cast<Type2>(types).Print();
}
UPDATE:
I consider the question to be solved thanks to Igor Tandetnik and mattlangford
As it happens in real life, if you think that you do not understand a thing you often miss more than one.
T == T1
a compiler does NOT call the template constuctor but rather copy constructor. One should keep in mind that apparently the constructor below alone is not enough to solve the general purpose case. That was noted in the comment heretemplate <typename T>
Type1(T t) : init_{std::is_same<Type1, T>::value} {}
static_cast<Type1>(types).Print();
static_cast<Type2>(types).Print();
template <typename T>
Type1() : init_{std::is_same<Type1, T>::value} {};
Upvotes: 0
Views: 55
Reputation: 1260
It seems like it's something with the copy constructor being automatically generated and used instead of the templated function. I added the copy constructor explicitly:
template <typename T>
Type1(T t) {}
Type1(const Type1& t) : init_{true} {}
to both types that seemed to work.
Another note would be to switch the print lines to:
static_cast<Type1&>(types).Print();
static_cast<Type2&>(types).Print();
since if you just static_cast
to the non-reference types there will be copies being made (if it's even defined behavior).
Upvotes: 1