Jor*_*eit 6 gcc templates clang sfinae c++11
我想实现一个小的trait类来确定一个类型是否已operator()正确重载,以便我可以查询类似的类型:
FunctorCheck<F, void(int, char)>::value
Run Code Online (Sandbox Code Playgroud)
最初,我对如何从这个问题实现这个问题有了一个想法,但在看了一篇关于TMP的Cppcon讲座之后,我突然意识到这个问题可以更优雅地解决.这就是我想出来的,它在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
{};
Run Code Online (Sandbox Code Playgroud)
您可能已经注意到,我正在使用建议的C++ 17 void_t在专业化的模板参数中利用SFINAE.当FunctorReturn收到Functor与参数列表不兼容的-type时,void_t<FunctorReturn<Functor, Args ...>>将形成格式,SFINAE将启动并且将实例化非专用版本.如果前一个表达式格式正确,则std::is_same比较返回类型以确定我们是否匹配.
在前面提到的讲座中,Walter Brown提到这种技术从第1天开始就在Clang上工作,并且从第1天开始就没有在GCC上工作,仅仅因为他们在标准未指定的内容上选择了不同的实现.但是,鉴于这个版本比我之前的版本更优雅,我有什么办法可以在GCC(> = 4.9)上进行编译吗?
(另外,有没有人知道在最近的Visual Studio版本中它会如何表现?)
这是CWG问题1558.在未指定的部分是一个别名模板处理的未使用的参数.在GCC <5.0中,未使用的参数不会导致替换失败,因此void_t 无法验证您的仿函数调用,并尝试实例化类模板特化,这会导致硬错误.
GCC(<5.0)的解决方法是以下实现:
template <typename...>
struct voider
{
using type = void;
};
template <typename... Ts>
using void_t = typename voider<Ts...>::type;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
802 次 |
| 最近记录: |