关于类模板和功能模板的SFINAE的问题

时间:2019-02-26 10:22:52

标签: c++ c++11 templates c++14

我尝试专用于STL容器的模板(函数或类)。我使用的标准是c ++ 14。

对于模板功能,我尝试如下代码。

template<typename... Args>
using int_t = int;

template<typename T, int_t
<
    typename T::value_type, //has defined the element type
    typename T::iterator, //has defined the iterator
    decltype(std::declval<T>().size()) //has defiend the "size()" function
    //other check...
> = 0>
void container_handler()
{
}

我认为,如果“ int_t”中不存在任何类型,则不会实例化模板函数,但是当我按以下方式调用模板函数时,不会发生编译错误。

container_handler<int>();

但是,使用类模板时会得到不同的结果。

template<typename... Args>
using int_t = int;

template<typename T , typename = int>
struct ContainerHandler;

template<typename T>
struct ContainerHandler<T, int_t
<
    typename T::value_type, //has defined the element type
    typename T::iterator, //has defined the iterator
    decltype(std::declval<T>().size()) //has defiend the "size()" function
    //other check...
>>
{
};

上面的代码有效,当我使用尚未定义特殊类型或函数的类型实例化类模板时,会发生编译错误。

ContainerHandler<int> handler1; //compile error
ContainerHandler<int, int> handler2; //compile error
ContainerHandler<vector<int>> handler3; //ok
ContainerHandler<vector<int>, int> handler4; //ok

此处的“ int_t”可以在c ++ 17中替换为“ void_t”。 我的问题是,为什么SFINAE规则与功能模板和类模板不同。 对于功能模板,我尝试了另一种方法,并且可以使用。

template<typename... Args>
struct type_container
{
    using int_t = int;
};

template<typename T, typename type_container
<
    typename T::value_type, //has defined the element type
    typename T::iterator, //has defined the iterator
    decltype(std::declval<T>().size()) //has defiend the "size()" function
    //other check...
>::int_t = 0>
void container_handler()
{
}

container_handler<int>(); //compile error
container_handler<int, 0>(); //compile error
container_handler<vector<int>>(); //ok
container_handler<vector<int>, 0>(); //ok

我不知道使用“ int_t”和“ type_container :: int_t”有什么区别。

1 个答案:

答案 0 :(得分:0)

以下两行之所以失败,是因为没有ContainerHandler的定义会使这些模板参数的模板实例化成功。

ContainerHandler<int> handler1; //compile error
ContainerHandler<int, int> handler2; //compile error

如果要提供模板的定义,例如像这样:

template<typename T , typename = int>
struct ContainerHandler {};

编译将成功。参见demo here

编辑:

  

不。我期望在调用模板函数“ container_handler();”时出现编译错误。 (在代码的第一部分)。

int_t的{​​{1}}参数具有默认值,这就是为什么它编译container_handler的原因 没有默认值将使编译失败。
参见demo here