std :: is_assignable和const指针对象

时间:2015-04-27 11:35:42

标签: c++ templates c++11 metaprogramming

尝试使用std::is_assignable

推断事物时,我遇到了一个小问题

我的代码:

#include <string>
#include <type_traits>

class Object{};

enum my_conv {
  string, const_object, object
};

template<typename T, typename V = void>
struct deducer;

template<typename T>
struct deducer<T, typename std::enable_if< std::is_constructible<std::string, T>::value >::type > {
  static const my_conv value = my_conv::string;
}; // (1) test for string                                                                                              

template<typename T>
struct deducer<T, typename std::enable_if< std::is_assignable<Object*&, T>::value >::type > {
  static const my_conv value = my_conv::object;
}; // (2) test for Object derived                                                                                      

template<typename T>
struct deducer<const T, typename std::enable_if< std::is_assignable<Object*&, T>::value >::type > {
  static const my_conv value = my_conv::const_object;
}; // (3) should test for const Object derived                                                                         

class Test : public Object {
public:
  Test() = default;
};

int main() {
  std::string   str;
  Test*         t = new Test;
  const Test*   tconst = static_cast<const Test*>(t);

  deducer<decltype(t)>::value;// deduce as (1)                                                                         
  deducer<decltype(str)>::value;//deduce as (2)                                                                        
  deducer<decltype(tconst)>::value;//fail to deduce as (3)... why?                                                     
}

而且我真的不明白为什么编译器无法实例化第三个推导者......

编辑:

测试时,我已经看到写过:

struct deducer<const T*, typename std::enable_if< std::is_assignable<Object*&, T*>::value >::type >

让它发挥作用,但我想我还需要一些解释......因为我还是第一次不明白什么是错的......

2 个答案:

答案 0 :(得分:2)

显然它不匹配(1)因为const Test *不能从std::string构建。

它将不匹配(2)因为指向const的指针不能分配给非const指针。

它不匹配(3)因为它是常量类型,而不是指向常量类型的指针。

请记住,如果T是指针类型Test*,那么const T是常量指针Test * const,而不是指向常量的指针{{1} }。

答案 1 :(得分:1)

tconst的类型是指向const的非const Test指针。因此,它与类模板专门化(2)匹配:

template<typename T>
struct deducer<T, // [...]

使用T = const Test*而不是(3),其匹配T const类型(例如Test* const,与const Test*不同)。

然而,它仍然无法编译,回到您不完整的主类模板,因为当尝试将const Test*(推导的T)分配给a时,可分配性测试不成功Object*&类型的指针(缺少const限定符)。