class 中的 C++ enable_if - 不同的破坏方式
C++ enable_if in class - different ways of destruction
我正在为嵌入式设备开发应用程序,因此我没有 type_traits
和 enable_if
(编译器质量差)。我自己创建了它们:
template <typename T>
struct is_pointer_t{
enum{value = false};
};
template <typename T>
struct is_pointer_t<T*>{
enum{value = true};
};
以及 consts
和 volatiles
的类似声明。
现在实施enable_if
:
template <bool boolean, typename T = void>
struct enable_if{};
template <typename T>
struct enable_if<true, T>{
typedef T type;
};
现在我想要一个 class,这取决于我使用指针还是普通类型,它是否调用它们的析构函数,所以如果我能有模板化的析构函数就太好了。但是我不知道该怎么做,因为我才刚刚开始理解模板编程。以下尝试失败:
template <typename T>
class pointerOrNot{
public:
template <typename U>
void one();
};
template <typename T>
template <typename enable_if<is_pointer_t<T>::value>::type>
void pointerOrNot<T>::one(){
std::cout << "Success1" << std::endl;
}
template <typename T>
template <typename enable_if<!is_pointer_t<T>::value>::type>
void pointerOrNot<T>::one(){
std::cout << "Success2" << std::endl;
}
它说它不符合定义。所以我尝试了以下:
template <typename T>
class pointerOrNot{
public:
template <typename enable_if<is_pointer_t<T>::value>::type>
void one();
template <typename enable_if<!is_pointer_t<T>::value>::type>
void one();
};
但是其中一个 one() 的模板为空类型,编译失败。我怎样才能做到这一点?也可以用析构函数来做到这一点吗?
首先让我们考虑以下 class 指针:
template <typename T>
struct Introducer{
void intro(){
std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
}
T mem;
Introducer(T m):mem(m){}
};
它适用于指针,但它也适用于 non-pointers:
Introducer<int> i(10);
i.intro();//just fine!
我们想在编译时检测这种误用,我们也将 Introducer 更改为
template <typename T>
struct Introducer{
typename enable_if<is_pointer_t<T>::value, void>::type //this is the return type of the function
intro(){
std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
}
...
};
现在编译器不允许我们将 non-pointer 与 Introducer 一起使用。在下一步中,我们希望通过 SFINAE:
为 non-pointers 提供一个特殊功能
template <typename T>
struct Introducer{
typename enable_if<is_pointer_t<T>::value, void>::type
intro(){
std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
}
typename enable_if<!is_pointer_t<T>::value, void>::type
intro(){
std::cout<<"I'm a non-pointer, my value is "<<mem<<std::endl;
}
...
};
见鬼,它连编译都不行!让我们仔细阅读有关SFINAE的文章:
If a substitution results in an invalid type or expression, type
deduction fails. An invalid type or expression is one that would be
ill-formed if written using the substituted arguments. Only invalid
types and expressions in the immediate context of the function type
and its template parameter types can result in a deduction failure.
T
不在直接上下文中,因此 SFINAE 不起作用,让我们将 T
放入直接上下文中:
template <typename T>
struct Introducer{
template <typename C=T>
typename enable_if<is_pointer_t<C>::value, void>::type
intro(){
std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
}
template <typename C=T>
typename enable_if<!is_pointer_t<C>::value, void>::type
intro(){
std::cout<<"I'm a non-pointer, my value is "<<mem<<std::endl;
}
...
};
现在是程序
int main(){
Introducer<float*> fp(NULL);
fp.intro();
//But this works also:
Introducer<int> i(10);
i.intro();
}
结果:
I'm a pointer, I point to adress 0
I'm a non-pointer, my value is 10
析构函数呢?最简单的方法是从析构函数中调用 SFINAE-destruction-function(我从未见过 SFINAE-destructor,也不知道如何写,但这并不意味着什么):
template <typename T>
struct Introducer{
...
~Introducer(){
intro();
std::cout<<"and I'm deleted..."<<std::endl;
}
};
我正在为嵌入式设备开发应用程序,因此我没有 type_traits
和 enable_if
(编译器质量差)。我自己创建了它们:
template <typename T>
struct is_pointer_t{
enum{value = false};
};
template <typename T>
struct is_pointer_t<T*>{
enum{value = true};
};
以及 consts
和 volatiles
的类似声明。
现在实施enable_if
:
template <bool boolean, typename T = void>
struct enable_if{};
template <typename T>
struct enable_if<true, T>{
typedef T type;
};
现在我想要一个 class,这取决于我使用指针还是普通类型,它是否调用它们的析构函数,所以如果我能有模板化的析构函数就太好了。但是我不知道该怎么做,因为我才刚刚开始理解模板编程。以下尝试失败:
template <typename T>
class pointerOrNot{
public:
template <typename U>
void one();
};
template <typename T>
template <typename enable_if<is_pointer_t<T>::value>::type>
void pointerOrNot<T>::one(){
std::cout << "Success1" << std::endl;
}
template <typename T>
template <typename enable_if<!is_pointer_t<T>::value>::type>
void pointerOrNot<T>::one(){
std::cout << "Success2" << std::endl;
}
它说它不符合定义。所以我尝试了以下:
template <typename T>
class pointerOrNot{
public:
template <typename enable_if<is_pointer_t<T>::value>::type>
void one();
template <typename enable_if<!is_pointer_t<T>::value>::type>
void one();
};
但是其中一个 one() 的模板为空类型,编译失败。我怎样才能做到这一点?也可以用析构函数来做到这一点吗?
首先让我们考虑以下 class 指针:
template <typename T>
struct Introducer{
void intro(){
std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
}
T mem;
Introducer(T m):mem(m){}
};
它适用于指针,但它也适用于 non-pointers:
Introducer<int> i(10);
i.intro();//just fine!
我们想在编译时检测这种误用,我们也将 Introducer 更改为
template <typename T>
struct Introducer{
typename enable_if<is_pointer_t<T>::value, void>::type //this is the return type of the function
intro(){
std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
}
...
};
现在编译器不允许我们将 non-pointer 与 Introducer 一起使用。在下一步中,我们希望通过 SFINAE:
为 non-pointers 提供一个特殊功能template <typename T>
struct Introducer{
typename enable_if<is_pointer_t<T>::value, void>::type
intro(){
std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
}
typename enable_if<!is_pointer_t<T>::value, void>::type
intro(){
std::cout<<"I'm a non-pointer, my value is "<<mem<<std::endl;
}
...
};
见鬼,它连编译都不行!让我们仔细阅读有关SFINAE的文章:
If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure.
T
不在直接上下文中,因此 SFINAE 不起作用,让我们将 T
放入直接上下文中:
template <typename T>
struct Introducer{
template <typename C=T>
typename enable_if<is_pointer_t<C>::value, void>::type
intro(){
std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
}
template <typename C=T>
typename enable_if<!is_pointer_t<C>::value, void>::type
intro(){
std::cout<<"I'm a non-pointer, my value is "<<mem<<std::endl;
}
...
};
现在是程序
int main(){
Introducer<float*> fp(NULL);
fp.intro();
//But this works also:
Introducer<int> i(10);
i.intro();
}
结果:
I'm a pointer, I point to adress 0
I'm a non-pointer, my value is 10
析构函数呢?最简单的方法是从析构函数中调用 SFINAE-destruction-function(我从未见过 SFINAE-destructor,也不知道如何写,但这并不意味着什么):
template <typename T>
struct Introducer{
...
~Introducer(){
intro();
std::cout<<"and I'm deleted..."<<std::endl;
}
};