我可以使用std::experimental::is_detected
来检查chips1_t
是否可以使用float*
(它不能)实例化,如下面的static_assert
所示:
#include <experimental/type_traits>
#include <type_traits>
template <typename, typename = void>
struct chips1;
template <typename T>
struct chips1<T*,std::enable_if_t<std::is_same<T,int>::value>> {
using type = int;
};
template <typename T> using chips1_t = typename chips1<T>::type;
static_assert(!std::experimental::is_detected<chips1_t,float*>::value,"");
如果我尝试使用chips2_t
进行检查,则下面显示的类似static_assert
将产生编译错误;关于失踪的type
成员。谁能告诉我为什么?
struct Base {};
template <typename>
struct chips2;
template <typename T>
struct chips2<T*> : std::enable_if_t<std::is_same<T,int>::value,Base> {
using type = int;
};
template <typename T> using chips2_t = typename chips2<T>::type;
static_assert(!std::experimental::is_detected<chips2_t,float*>::value,"");
答案 0 :(得分:2)
在第二种情况下,基类不是模板类型的一部分,因此在SFINAE期间不考虑它(它是依赖基类)
实例化
template <typename T>
struct chips2<T*>
成功,然后编译失败,因为它派生自std::enable_if_t<std::is_same<T,int>::value,Base>
,这将成为一个格式错误的表达式。
您不能通过基类 * 来专门化模板。
例如,你不可能有两个竞争专长,如:
template <typename T>
struct chips2<T*> : std::enable_if_t<std::is_same<T,int>::value,Base> {
using type = int;
};
template <typename T>
struct chips2<T*> : std::enable_if_t<!std::is_same<T,int>::value,Base> {
using type = float;
};
从专业化的角度来看,它们被认为是相同的(即,从命名的角度看它们是相同的,因此编译器会认为第二个是第一个的重新声明)。唯一重要的部分是结肠:
在第一种情况下,您的enable_if
直接属于模板专精化,因此SFINAE正常运作。
在第二个问题中,您实际上无法使用chips2
以外的任何内容实例化int*
,请参阅以下示例:
struct Base {};
template <typename>
struct chips2
{};
template <typename T>
struct chips2<T*>
: std::enable_if_t<std::is_same<T,int>::value, Base>
{};
int main(){
chips2<float*> c;
}
您可能倾向于认为SFINAE将为c
选择基类模板,但实际上它选择了专门化chips2<T*>
,因为我上面所说的,编译失败。
* [temp.spec]
的相关标准显式专用的类的名称应为 simple-template-id。
simple-template-id 的形式如下:
template-name&lt; template-argument-listopt&gt;
e.g。 chips2<T*>
。请注意,没有选项也包括它从