enable_if 对于没有 return 类型的函数

enable_if for functions with no return type pulled in it

我最近遇到了一个有趣的 enable_if 用法版本,它有条件地启用一个函数,可读性稍好一些,因为该函数的 return 类型不是 enable_if 的一部分(请参阅 cleaner_usage):

#include <type_traits>

using maybe_integral = int /* = or float -- then won't compile */;
using return_type = int;

typename std::enable_if<std::is_integral<maybe_integral>::value, return_type>::type
traditional_usage()
{
    return 1;
}

template<typename std::enable_if<std::is_integral<maybe_integral>::value, int>::type = 0>
return_type cleaner_usage()
{
    return 2;
}

int main()
{
    return traditional_usage() + cleaner_usage();
}

对于失败案例,机制很明确(没有 type 成员)。

但它在其他情况下究竟是如何工作的呢?因为看起来 int typedef 字段被替换为具有意外分配的模板类型参数。

成功案例:

template<typename std::enable_if<std::is_integral<float>::value, int>::type = 0>
return_type cleaner_usage()
{
    return 2;
}

将等同于:

template<int = 0>
return_type cleaner_usage()
{
    return 2;
}

这是完全合法的,因为允许某些值类型出现在模板参数上下文中。我相信这些被正式称为非类型模板参数,如§14.1/4所述:

A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

  • integral or enumeration type,
  • pointer to object or pointer to function,
  • lvalue reference to object or lvalue reference to function,
  • pointer to member,
  • std::nullptr_t.