为什么 SFINAE 没有给出递增 bool 的正确结果?
Why does SFINAE not give the correct result for incrementing bool?
我写了一个 is_incrementable
这样的特征:
#include <type_traits>
template <typename T, typename = void>
struct is_incrementable : std::false_type {};
template <typename T>
struct is_incrementable<T, std::void_t<decltype(++std::declval<T&>())>>
: std::true_type {};
template <typename T>
constexpr bool is_incrementable_v = is_incrementable<T>::value;
当我用 -std=c++17
将它应用到 bool
时,它 returns true
:
// This compiles
static_assert(is_incrementable_v<bool>, "");
但是在 c++17 下不允许递增 bool
。事实上,如果我尝试这样做,我会得到一个错误:
bool b = false;
++b;
结果:
error: ISO C++17 does not allow incrementing expression of type bool [-Wincrement-bool]
为什么 SFINAE 报告 bool
是可递增的,而编译器显然不允许它?
编译器资源管理器:https://godbolt.org/g/DDFYBf
看起来 Clang 错误地允许在未计算的上下文中增加 bool
值。
我们可以使用 C++20 概念简化您的示例:
template<class T>
concept is_incrementable = requires(T t) {
{ ++t };
};
int main() {
static_assert( is_incrementable<int> );
static_assert( !is_incrementable<bool> ); // Clang error here
}
此程序在 GCC 和 MSVC 中被接受,但 Clang 在这里显示相同的错误行为,演示:https://gcc.godbolt.org/z/YEnKfG8T5
我认为这是 Clang 的错误,所以提交了错误报告:https://bugs.llvm.org/show_bug.cgi?id=52280
我写了一个 is_incrementable
这样的特征:
#include <type_traits>
template <typename T, typename = void>
struct is_incrementable : std::false_type {};
template <typename T>
struct is_incrementable<T, std::void_t<decltype(++std::declval<T&>())>>
: std::true_type {};
template <typename T>
constexpr bool is_incrementable_v = is_incrementable<T>::value;
当我用 -std=c++17
将它应用到 bool
时,它 returns true
:
// This compiles
static_assert(is_incrementable_v<bool>, "");
但是在 c++17 下不允许递增 bool
。事实上,如果我尝试这样做,我会得到一个错误:
bool b = false;
++b;
结果:
error: ISO C++17 does not allow incrementing expression of type bool [-Wincrement-bool]
为什么 SFINAE 报告 bool
是可递增的,而编译器显然不允许它?
编译器资源管理器:https://godbolt.org/g/DDFYBf
看起来 Clang 错误地允许在未计算的上下文中增加 bool
值。
我们可以使用 C++20 概念简化您的示例:
template<class T>
concept is_incrementable = requires(T t) {
{ ++t };
};
int main() {
static_assert( is_incrementable<int> );
static_assert( !is_incrementable<bool> ); // Clang error here
}
此程序在 GCC 和 MSVC 中被接受,但 Clang 在这里显示相同的错误行为,演示:https://gcc.godbolt.org/z/YEnKfG8T5
我认为这是 Clang 的错误,所以提交了错误报告:https://bugs.llvm.org/show_bug.cgi?id=52280