c++ - 无法在 MSVC10 中使用 SFINAE、类型特征和 static_assert

标签 c++ visual-studio-2010 c++11 visual-c++ static-assert

我一直在研究使用一些明智的静态断言来改进错误消息。这是一个例子:

#include <type_traits>
template<typename T> struct is_less_than_comparable {
    template<typename Test> static char test(decltype(*static_cast<Test*>(nullptr) < *static_cast<Test*>(nullptr)));
    template<typename Test> static int test(...);
    static const bool value = std::is_same<char, decltype(test<T>(true))>::value;
};
template<typename K, typename V> class map {
public:
    static_assert(is_less_than_comparable<K>::value, "Key type must be less-than comparable!");
};
struct x {};
int main() {
    map<x, int> intmap;
}

IDEONE 会愉快地拒绝此代码,并给出我希望得到的漂亮、干净的错误消息(无论如何,一旦您将 nullptr 替换为 0)。但是 MSVC 不会触发静态断言并编译这段代码就好了——即使我添加了一些成员函数并开始调用它们也是如此。

最佳答案

问题在于 VC++ 2010 对元函数 is_less_than_comparable 的处理, 不适用于 static_assert .

如果将代码更改为:

static const bool value = std::is_same<double, decltype(test<T>(true))>::value;

那么无论选择哪个重载,它都将为 false。然后触发断言。

显然选择了错误的重载,SFINAE 没有删除带有 char 的候选者返回类型。


更简单的测试(错误地打印 1 ):

#include <type_traits>
template<typename T> struct is_less_than_comparable {
    template<typename Test> static char test(decltype(*static_cast<Test*>(nullptr) < *static_cast<Test*>(nullptr)) b);
    template<typename Test> static int test(...);
    static const bool value = std::is_same<char, decltype(test<T>(true))>::value;
};
struct x {};
#include <iostream>
int main() {
    std::cout << is_less_than_comparable<x>::value << std::endl;
}

编译器无缘无故地提供一个bool operator<(x, x)运算符,从而生成int is_less_than_comparable<T>::test<T>(bool) .如果提供了用户定义的比较运算符,则会正确选取其返回类型。该运算符不包含其中一个 header ,我可以重现 decltype解析为 bool不包含 header 。

这会产生正确的错误:

decltype(*(x*)nullptr < *(x*)nullptr) b;

error C2676: binary '<' : 'x' does not define this operator or a conversion to a type acceptable to the predefined operator

我认为这与 VC++ 不执行模板相关参数的两阶段查找有关。

关于c++ - 无法在 MSVC10 中使用 SFINAE、类型特征和 static_assert,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6300203/

相关文章:

c++ - 在 unordered_set 中插入一个新元素 : should the hint be end()?

c++ - 使用 atomic_flag 自旋锁进行内存排序

c++ - g++ 为定义的函数抛出大量 'undefined reference'

c - 调试 Visual Studio C 项目的 NMake 文件

c++ - 功能模板的特化,不改变其原型(prototype)

c# - 是否有用于 WPF XAML 文件的独立可视化编辑器?

c# - Visual Studio 2010 自动附加到进程

c++ - std::move 在 vector::insert 和 push_back 上的行为不同

c++ - 我应该将哪个版本的 boost 与 c++ visual-studio-2005 一起使用?

c++ - 将 unsigned long long 与 signed long long 结果相减?