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

Understanding why compile-time boolean algebra doesn't work

本文关键字:布尔代数 不起作用 编译 为什么 了解      更新时间:2023-10-16

我试图实现一个基本的模板元编程结构,它确定类型列表是否都使用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,我得到以下编译器错误:

'check_same':模板参数太少

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


以下代码将编译失败:

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

c++中的类模板不能像函数那样"重载"。您不能用不同的参数集一次又一次地重新声明同一个模板,并期望它能够编译。例如,这将不会编译

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;
};

试试这个:

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都有效。