尝试使用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 >
让它发挥作用,但我想我还需要一些解释......因为我还是第一次不明白什么是错的......
答案 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
限定符)。