C ++ 11:模板参数中的SFINAE,GCC与Clang

乔伦·海特

我想实现一个小小的trait-class来确定类型是否operator()正确地重载,以便可以查询如下类型:

FunctorCheck<F, void(int, char)>::value

最初,我对这个问题有一个解决方案,但是看了Cppcon关于TMP的演讲,我突然意识到可以更优雅地解决这个问题。这是我想出的,它可以在Clang 3.5.0上完美编译和运行:

template <typename ...>
using void_t = void;

template <typename Functor, typename ... Args>
using FunctorReturn = decltype(declval<Functor>()(declval<Args>()...));

template <typename Functor, typename Signature, typename = void>
struct FunctorCheck: public std::false_type
{};

template <typename Functor, typename R, typename ... Args>
struct FunctorCheck<Functor, R(Args...), 
    void_t<FunctorReturn<Functor, Args ...>> // SFINAE can kick in here
> : public std::is_same<R, FunctorReturn<Functor, Args ...>>::type
{};

您可能已经注意到,我正在使用建议的C ++ 17void_t在专业化模板参数中利用SFINAE。FunctorReturn接收到Functor与参数列表不兼容-type时,其void_t<FunctorReturn<Functor, Args ...>>格式将不正确,SFINAE将加入,非专业版本将被实例化。如果前一个表达式格式正确,则std::is_same比较返回类型以确定我们是否有匹配项。

在前面提到的演讲中,Walter Brown提到该技术从Clang的第一天起就起作用了,而从第一天起就没有在GCC上起作用,这仅仅是因为他们在标准未指定的内容上选择了不同的实现。但是,鉴于此版本比我以前拥有的版本更加优雅,我是否可以做些什么才能在GCC(> = 4.9)上进行编译?

(此外,是否有人对最新版本的Visual Studio的行为有任何线索?)

皮特·斯科特尼克

这是CWG问题1558未指定的部分是一个别名模板处理的未使用的参数。在GCC <5.0中,未使用的参数不会导致替换失败,因此void_t 无法验证您的functor调用,并尝试实例化类模板的特殊化,从而导致硬错误。

GCC(<5.0)的一种解决方法是以下实现:

template <typename...>
struct voider
{
    using type = void;
};

template <typename... Ts>
using void_t = typename voider<Ts...>::type;

演示

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

C ++ 11模板中的默认位置参数

在C ++ 11中枚举布尔模板参数

曾经在旧版gcc中使用的C ++模板在clang ++中导致“阴影模板参数”错误

Clang和GCC在自动说明符中对强制转换C ++ 17中非类型模板参数的意见不一致

GCC中的C ++模板

数据成员SFINAE的C ++ 17测试:gcc与clang

C ++朋友功能模板重载和SFINAE在clang ++,g ++,vc ++中的不同行为(C ++ 14模式)

C ++ 11中的可变参数模板和多重继承

成员函数指针的decltype作为c ++ 11中的模板参数

基于C ++ 11中的模板参数选择数组大小?

如何推断C ++ 11中的模板参数类型?

C ++中的模板参数

在c ++ 11中调用模板参数的函数,其中模板参数为chrono :: system_clock

C ++ 11中具有多个模板参数的模板函数的专业化

参数名模板的参数化模板c ++ 11

c ++模板递归双链表错误gcc(但clang ++接受)

在C ++ 11中使用模板参数的递归可变参数void函数

C ++ 11中的模板约束

c ++ 11递归可变参数模板

C ++ 11模板,参数包的别名

C ++ 11中的模板模板错误

C ++ 17和C ++ 11中的非类型模板参数之间有什么区别?

在C ++中更改模板模板参数

如何在C ++ 11中约束参数包类型?以及如何在cpp中实现模板?

在C ++ 11中,陶氏可以引用模板参数中定义的枚举类

在C ++ 11中非平凡初始化模板类的静态成员而没有clang警告

获取在C ++ 11中具有可变参数模板的函数的地址

C ++ 11中常量表达式的模板int参数

为什么我不能在C ++ 11中使用constexpr指针作为模板参数?