Reputation: 3575
Is there an way to call different constructors of same class based on different template parameter.
template<class T>
class X {
public:
T a;
X<char>() {
std::cout << "char ctor called" << std::endl;
}
X<int>() {
std::cout << "int ctor called" << std::endl;
}
};
int main() {
X<char> x;
X<int> y;
}
I think constructors in the class are not valid, but is there any other way to do that?
Upvotes: 0
Views: 384
Reputation: 217085
There are several ways:
(full) specialization of the member:
template<class T>
class X {
public:
T a;
X();
};
template <>
X<char>::X() : a('\0') { std::cout << "char ctor called" << std::endl; }
template <>
X<int>::X() : a(0) { std::cout << "int ctor called" << std::endl; }
Specialize the whole class (so requires to duplicate some code though)
template<class T>
class X;
template <>
class X<char> {
public:
char a;
X() : a('\0') { std::cout << "char ctor called" << std::endl; }
};
template <>
class X<int> {
public:
int a;
X() : a(0) { std::cout << "int ctor called" << std::endl; }
};
if constexpr
of C++17 (but doesn't handle initializer list):
template<class T>
class X {
public:
T a;
X() : a(0) {
if constexpr (std::is_same_v<char, T>) {
std::cout << "char ctor called" << std::endl;
} else if constexpr (std::is_same_v<int, T>) {
std::cout << "int ctor called" << std::endl;
}
}
};
requires
for C++20:
template<class T>
class X {
public:
T a;
X() requires(std::is_same_v<char, T>) : a('\0') {
std::cout << "char ctor called" << std::endl;
}
X() requires(std::is_same_v<int, T>) : a(0) {
std::cout << "int ctor called" << std::endl;
}
};
Upvotes: 3
Reputation: 26272
Just another alternative - tag dispatch:
template<class T>
class X {
public:
// ...
X() : X(Tag<T>{}) {}
private:
template<class> struct Tag {};
X(Tag<char>) {
// ...
}
X(Tag<int>) {
// ...
}
template<class U> X(Tag<U>) {
// ...
}
};
Upvotes: 2
Reputation: 20569
You can use if constexpr
:
template <class T>
class X {
public:
// ...
X()
{
if constexpr (std::is_same_v<T, int>) {
// ...
} else if constexpr (std::is_same_v<T, char>) {
// ...
} else {
// ...
}
}
};
Upvotes: 2
Reputation: 3
Yes,see http://www.cplusplus.com/doc/oldtutorial/templates/
You can do this:
template<class T>
class X {
public:
T a;
X() {
std::cout << "basic template\n" ;
}
};
template<>
class X<char> {
public:
char a;
X() {
std::cout << "char ctor called\n" ;
}
};
template<>
class X<int> {
public:
int a;
X() {
std::cout << "int ctor called\n";
}
};
int main(){
X<int> xint;
X<char> xchar;
X<string> xstring;
return 0;
}
You will see in the output window:
int ctor called
char ctor called
basic template
Upvotes: 0