理解为什么编译时布尔代数不起作用

时间:2014-07-23 15:15:39

标签: c++ templates c++11 template-meta-programming

我正在尝试实现一个基本模板元编程结构,它使用std::is_same确定类型列表是否完全相同。我尝试按如下方式实现它:

template <typename T, typename U, typename... Args>
struct check_same {
     static const bool value = std::is_same<T, U>::value && check_same<U, Args...>::value;
};

template <typename T, typename U>
struct check_same {
     static const bool value = std::is_same<T, U>::value;
};

但是,如果我尝试实例化check_same,我会收到以下编译器错误:

  

&#39; check_same&#39; :模板参数太少

为什么这不是执行编译时布尔代数的有效方法?当然所涉及的所有表达式都是constexpr(或const,因为MSVC还没有实现constexpr),它应该编译吗?


以下将无法编译:

int main() 
{
    static_assert( check_same<int, unsigned int, float>::value, "Types must be the same" );

    return 0;
}

2 个答案:

答案 0 :(得分:4)

C ++中的类模板不能超载&#34;喜欢的功能。您不能使用不同的参数集一次又一次地重新声明相同的模板,并期望它能够编译。例如,这不会编译

template <typename A> struct S {};
template <typename A, typename B> struct S {};

它不会编译,因为它试图两次声明模板类S。这是非法的。

您的代码遇到完全相同的错误:您已经声明了模板check_same两次。你不能这样做。

您显然尝试使用的技术应基于模板专业化,而不是基于模板重新声明。您只需要声明一次主要模板

template <typename T, typename U, typename... Args>
struct check_same {
     static const bool value = std::is_same<T, U>::value && check_same<U, Args...>::value;
};

然后为特定的,更受限制的参数集提供该主要模板的部分特化

template <typename T, typename U>
struct check_same<T, U> {
     static const bool value = std::is_same<T, U>::value;
};

答案 1 :(得分:2)

试试这个:

template <typename T, typename... Args>
struct check_same: std::true_type {};

template <typename T, typename U, typename...Args>
struct check_same<T,U,Args...>: std::integral_constant<bool,
  std::is_same<T,U>::value && check_same<U, Args...>::value
> {};

第一个只在只有一个参数的情况下进行评估。第二个专业化获得2个或更多。

如果传递0个参数,则会出错。我认为你也应该处理这个问题:

template <typename... Args>
struct check_same: std::true_type {};

template <typename T, typename U, typename...Args>
struct check_same<T,U,Args...>: std::integral_constant<bool,
  std::is_same<T,U>::value && check_same<U, Args...>::value
> {};

实际上不需要专门化,因为第一个适用于0和1参数。