我有一个带有一个模板参数'T'的模板类。我希望这个类有一个构造函数,但如果T是char,那么只需要有一个额外的构造函数"const-char*"作为参数。
template <typename T>
class Container
{
public:
// Construct a container from an array of T's
Container(const T* data, int count);
// For char only construct a container from a nul terminated string
// I *only* want this constructor to be valid when T is char
Container(const T* data);
};
有什么方法可以实现这一点,这样我就可以做到:-
const char* init = "Hello";
Container<char> data = init;
将编译但
const int init[] = {1, 3, 4};
Container<int> data = init;
不会编译。
您可以将其封装在构造函数模板中并使用SFINAE:
template <typename U=T,
typename = std::enable_if_t<std::is_same<U, char>::value>>
Container(const U* )
{
...
}
这样,对于Container<char>
,这个构造函数是可行的,但对于Container<int>
,它将是格式错误的,并从重载集中删除。
一个较小的替代方案是:
Container(const char* ) {
static_assert(std::is_same<T, char>::value, "!");
}
当你需要const char*
构造函数时,这仍然会给你它,而其他T
s没有const T*
构造函数。但我们仍然有std::is_constructible<Container<int>, const char*>
,这可能会破坏其他逻辑。所以坚持SFINAE。
您也可以使用静态断言
#include <type_traits>
template <typename T>
void Foo(T) {
static_assert(std::is_same<T, const char*>::value, "T must be const char *");
}
int main(int argc, char* argv[])
{
const char* c = "c";
Foo(c); // compile
Foo(1); // don't compile
}
您可以为char:编写构造函数
template <> Container<char>::Container(const char* data) {}
以下是示例:
Videone
这被称为模板专业化:
template<>
class Container<char>
{
public:
Container(const char *);
// ... the rest of the class declaration
};
现在,从所有意图和目的来看,这实际上是创建一个单独的类。除了构造函数之外,您还必须编写和声明它的所有其他方法。这可能需要对主模板类进行大量的代码复制,但通常可以在公共继承和/或基类的帮助下进行一些组织。
所有这些都到位了:
Container<int>
将解析为您的主模板,以及
Container<char>
让你上专业课。专业化本质上是根据模板参数从几个备选模板中选择一个。