如何在编译时评估 Primitive 与 Class 模板?

How to evaluate Primitive vs Class templates at compilation time?

当我们做...

template <typename T>
void foo(T x)
{
   if (is_fundamental<T>::value)
   {
       ...
   } else
   {
     ...
   }
}

我认为 if 语句(以及 is_fundamental<T>::value)是在 运行 时计算的,对吗?

如果是,有没有办法在编译时进行这个评估?我想要类似...

template <primitive_typename T>
void foo(T x)
{
   ...
}


template <noPrimitive_typename T>
void foo(T x)
{
   ...
}

一个解决方案是重载所有可能的原始类型,但这并不是一个真正令人满意的解决方案,因为它需要多次复制原始类型的代码。有没有办法用一个类型名来引用所有基元?

标签调度呢?

template <typename T>
void fooHelper (T t, std::true_type const &)
 { /* true case */ }

template <typename T>
void fooHelper (T t, std::false_type const &)
 { /* false case */ }

template <typename T>
void foo (T t)
 { fooHelper(t, std::is_fundamental<T>{}); }

在 C++17 中,if constexpr 语句在编译时评估条件并丢弃未选择的分支:

if constexpr(std::is_fundamental_v<T>) {
    // do something with x
} else {
    // do something else with x
}

一种老式的方法是使用标签分派:

template <typename FundamentalType>
void foo_helper(FundamentalType x, std::true_type);

template <typename NonFundamentalType>
void foo_helper(NonFundamentalType x, std::false_type);

template <typename T>
void foo(T x) {
    foo_helper(x, std::is_fundamental<T>{});
}

您也可以使用部分专用的帮助程序结构,但需要更多代码。