std :: is_same无法使用bool

Rai*_*ain 1 c++ templates traits c++11

  #include <array>
  template<typename T>
  void Func(T Param)
     {
     int Val = 0;
     if (std::is_same<T, bool>::value)
        Val += Param ? 1 : 0;
     }

  int main() 
     {
     std::array<int, 10> A;
     Func(A);
     return 0;
     }
Run Code Online (Sandbox Code Playgroud)

当我用gcc或MSVC编译时,我得到:

Error C2440 '?': cannot convert from 'std::array<int,10>' to 'bool'

不应该编译器甚至不编译,Val += Param ? 1 : 0;因为std::is_same<std::array<int, 10>, bool>::value是0?

Edg*_*jān 6

在当前场景中,当编译器尝试实例化Func模板时,它会看到:

Val += Param ? 1 : 0;
Run Code Online (Sandbox Code Playgroud)

哪有Param类型std::array<int, 10>,所以它抱怨.

问题是if子句std::is_same在函数模板实例化期间没有神奇地删除代码的一部分.

从C++ 17开始,您可以使用if constexpr:

if constexpr (std::is_same_v<T, bool>)
   Val += Param ? 1 : 0;
}
Run Code Online (Sandbox Code Playgroud)

这解决了这个问题.

在C++ 17之前,您可以使用标签分派进行一些实验.例如,类似的东西应该工作:

template<typename T>
auto get(const T& p, std::true_type) {
    return p ? 1 : 0;
}

template<typename T>
auto get(const T& p, std::false_type) {
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后:

template<typename T>
void Func(T Param)
{
    int Val = 0;        
    // ...        
    Val += get(Param, std::is_same<T, bool>{});
}
Run Code Online (Sandbox Code Playgroud)

Wandbox示例