仅用于模板化类型的附加构造函数<char>



我有一个带有一个模板参数'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>

让你上专业课。专业化本质上是根据模板参数从几个备选模板中选择一个。

最新更新