“template<class = enable_if_t<...>>” 是什么意思?

10

我一直在阅读STL文件,以学习更好的代码格式化方式和提高效率的技巧。我一直在阅读线程文件,但有些代码的作用我无法理解。

template<class _Fn,
    class... _Args,
    class = enable_if_t<!is_same<decay_t<_Fn>, thread>::value>>
    explicit thread(_Fn&& _Fx, _Args&&... _Ax)
    {   // construct with _Fx(_Ax...)
    ...
    }

std::enable_if_t is

template<bool _Test,
    class _Ty = void>
    using enable_if_t = typename enable_if<_Test, _Ty>::type;

template<class _Ty>
    struct enable_if<true, _Ty>
    {   // type is _Ty for _Test
    using type = _Ty;
    };

这段代码中的thread和str1common STLs都受版权保护。

我唯一的问题是class = enable_if_t<...>是什么意思?


这是一个带有默认参数的未命名模板参数。它只是为了确保enable_if_t解析为一种类型。 - François Andrieux
一篇不错的阅读材料:http://en.cppreference.com/w/cpp/types/enable_if - NathanOliver
4
我肯定不建议您阅读STL文件。 - SergeyA
1个回答

9

查找 S.F.I.N.A.E.:“Substitution Failure Is Not An Error”。

看一个可能的实现 std::enable_ifstd::enable_if_t 只是一个辅助 using,C++14 引入,以更简单的方式访问type)。

template<bool B, class T = void>
struct enable_if {};

template<class T>
struct enable_if<true, T> { typedef T type; };

当且仅当模板布尔值(第一个模板参数)为true时,才会生成iff(即如果且仅如果)语句。在这种情况下,定义了std::enable_if<...>::type(类型在第二个模板参数中;如果没有指定,则为void)。

简单来说,在你的示例中,你拥有以上特性。

template<class _Fn,
    class... _Args,
    class = enable_if_t<!is_same<decay_t<_Fn>, thread>::value>>
    explicit thread(_Fn&& _Fx, _Args&&... _Ax)
    {   // construct with _Fx(_Ax...)
    ...
    }

enable_if_t(也就是typename std::enable_if <...> ::type )仅在第一个值(!std::is_same <typename std::decay <_Fn> ::type,thread> ::value)为 true 时可用。

也就是说:

  • 如果!std::is_same <typename std::decay <_Fn> ::type,thread> ::valuetrue,则执行替换class = enable_if_t<!is_same<decay_t<_Fn>, thread>::value>>并实现该函数。

  • 如果!std::is_same <typename std::decay <_Fn> ::type,thread> ::valuefalse,则替换class = enable_if_t<!is_same<decay_t<_Fn>, thread>::value>>失败,该函数未被实现 但这不是错误(SFINAE)

为什么语言允许这样做?

因为例如您可以实现该函数的两个版本。

template<class _Fn,
    class... _Args, //  vvvv true case
    class = enable_if_t<true == is_same<decay_t<_Fn>, thread>::value>>
    explicit thread(_Fn&& _Fx, _Args&&... _Ax)
    { /* do something */ }

template<class _Fn,
    class... _Args, //  vvvvv false case
    class = enable_if_t<false == is_same<decay_t<_Fn>, thread>::value>>
    explicit thread(_Fn&& _Fx, _Args&&... _Ax)
    { /* do something else */ }

建议:搜索SFINAE并学习它,因为它是现代C ++的重要部分。

非常感谢。这正是我认为它正在做的事情,但我无法找到任何支持这个想法的东西。SFINAE正是我想要了解更多的东西。 - Cody W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接