作为理解std::enable_if用法的一项练习,我尝试实现一个包装类(struct),以在任何给定的时间点表示特定类型:
#include<type_traits>
#include<typeinfo>
#include<iostream>
using std::enable_if;
using std::is_same;
using std::cout;
using std::endl;
template<typename T>
struct type_wrap{
type_wrap(typename enable_if<is_same<int,T>::value,T>::type&& rrT):value(rrT){
cout << "The wrapped type is " << typeid(value).name() << endl;
cout << "The wrapped value is " << value << endl;
}
type_wrap(typename enable_if<is_same<float,T>::value,T>::type && rrT):value(rrT){
cout << "The wrapped type is " << typeid(value).name() << endl;
cout << "The wrapped value is " << value << endl;
}
T& value;
};
int main(){
type_wrap<int>(0);
type_wrap<float>(0.5);
return(0);
}上述代码未编译:
so_main.cpp:16:47: error: no type named 'type' in 'std::__1::enable_if<false, int>'; 'enable_if' cannot be used to disable this declaration
type_wrap(typename enable_if<is_same<float,T>::value,T>::type && rrT):value(rrT){
^~~~~~~~~~~~~~~~~~~~~~~
so_main.cpp:26:9: note: in instantiation of template class 'type_wrap<int>' requested here
type_wrap<int>(0);
^
so_main.cpp:12:47: error: no type named 'type' in 'std::__1::enable_if<false, float>'; 'enable_if' cannot be used to disable this declaration
type_wrap(typename enable_if<is_same<int,T>::value,T>::type&& rrT):value(rrT){
^~~~~~~~~~~~~~~~~~~~~
so_main.cpp:27:9: note: in instantiation of template class 'type_wrap<float>' requested here
type_wrap<float>(0.5);
^
2 errors generated.如果我要删除一个重载的构造函数,并从main()中进行相应的实例化,代码就可以工作。但这违背了这次演习的全部目的。
有人能指出编译错误的原因吗?
发布于 2018-03-29 08:30:48
SFINAE工作在模板方法(/constructor)上,这里您的类是模板,您可以使用以下方法(即使在您的情况下专门化看起来更简单/更好):
template<typename T>
struct type_wrap{
template <typename U,
std::enable_if_t<std::is_same<int, U>::value
&& is_same<int, T>::value>* = nullptr>
type_wrap(U arg) : value(arg){
// Int case
std::cout << "The wrapped type is " << typeid(value).name() << std::endl;
std::cout << "The wrapped value is " << value << std::endl;
}
template <typename U,
std::enable_if_t<std::is_same<float, U>::value
&& is_same<float, T>::value>* = nullptr>
type_wrap(U arg) : value(arg){
// float case
std::cout << "The wrapped type is " << typeid(value).name() << std::endl;
std::cout << "The wrapped value is " << value << std::endl;
}
T value;
};演示
发布于 2018-03-29 05:15:58
有人能指出编译错误的原因吗?
因为std::enable_if将使您的构造函数之一成为非法,具体取决于以下每一个:
type_wrap<int>(0);
type_wrap<float>(0.5);int或double将迫使std::is_same的另一边拥有false,type
template<bool B, class T = void>
struct enable_if {}; // int or float will get this on each constructor.
template<class T>
struct enable_if<true, T> { typedef T type; };相反,可以按以下方式使用模板专门化:
template<typename T>
struct type_wrap;
template<>
struct type_wrap<float>
{
type_wrap(float&& rrT) :value(rrT) {
cout << "The wrapped type is " << typeid(value).name() << endl;
cout << "The wrapped value is " << value << endl;
}
float& value;
};
template<>
struct type_wrap<int>
{
type_wrap(int&& rrT) :value(rrT) {
cout << "The wrapped type is " << typeid(value).name() << endl;
cout << "The wrapped value is " << value << endl;
}
int& value;
};如果您的编译器支持C++17,那么if constexpr使它更简单、更直接:
template<typename T>
struct type_wrap
{
type_wrap(T&& rrT):value(rrT)
{
if constexpr (std::is_same<int, T>::value)
{
cout << "The wrapped type is " << typeid(value).name() << endl;
cout << "The wrapped value is " << value << endl;
}
else
{
cout << "The wrapped type is " << typeid(value).name() << endl;
cout << "The wrapped value is " << value << endl;
}
}
T& value;
};https://stackoverflow.com/questions/49548082
复制相似问题