2011-06-09 49 views
0

我一直在研究使用一些明智的静态断言来改进错误消息。这里有一个例子:不能在MSVC10中使用SFINAE,类型traits和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将愉快地拒绝这个代码与漂亮,干净的错误消息,我希望能得到(一旦你用0替换nullptr,反正)。但是MSVC不会触发静态断言并编译这些代码 - 即使我添加了一些成员函数并开始调用它们。

+0

代码不编译我。是否需要一些额外的头文件? – 2011-06-09 22:58:33

+0

@ Ben Voigt:'' – Puppy 2011-06-09 23:07:44

+0

我认为这与VC++没有执行模板相关参数的两阶段查找有关。 – 2011-06-09 23:28:24

回答

1

问题在于VC++ 2010处理元函数is_less_than_comparable,而不是static_assert

如果你的代码更改为:

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

然后,它会是假的不管哪个超载采摘。断言然后发生。

很明显错误的超载正在被选中,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)。如果提供了用户定义的比较运算符,则会正确拾取其返回类型。该操作员没有加入其中一个标题,我可以重新编写decltype解析为bool,不包含标题。

这将生成正确的错误:

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++不执行的模板依赖的论点两阶段查找。

1

我不能确定你要找的内容在这里的答案,所以这里是一个类型的特点是工作在VC++ 2010罚款:

#include <type_traits> 

namespace supports 
{ 
    namespace details 
    { 
     struct return_t { }; 

     template<typename T> 
     static T& make(); 
    } 

    template<typename T> 
    details::return_t operator <(T const&, T const&); 

    template<typename T> 
    struct less_than : std::integral_constant< 
     bool, 
     !std::is_same< 
      decltype(details::make<T>() < details::make<T>()), 
      details::return_t 
     >::value 
    > { }; 
} 
+0

最近添加的运营商特征,似乎工作,即使是免费的'operator <'函数。 – 2011-06-10 04:00:06

相关问题