是否有可能(并且是一个好主意)根据其元素的类型有条件地定义一些容器类(template<typename ThingType> class Container
)的方法?我第一次认为这是可能的阅读后std::enable_if
,但现在我不确定我理解。
std::is_base_of<ThingBase, ThingType>::value
为false
的情况下,将不定义p
的返回类型。我认为编译器只会实例化一个类的对象而不使用该方法。但结果是它不能编译。
是否有其他工具可以完成这项工作?或者我应该写两个Container
类,有不同的行为取决于ThingType
是什么?或者这是一份专精的工作。
#include <iostream>
#include <type_traits>
#include <vector>
class ThingBase {
public:
virtual void printHi() = 0;
};
class Thing : public ThingBase
{
void printHi(){
std::cout << "hin";
}
};
template<typename ThingType>
class Container{
private:
std::vector<ThingType> m_things;
public:
typename std::enable_if<std::is_base_of<ThingBase, ThingType>::value>::type p()
{
m_things[0].printHi();
};
};
int main() {
//Container<Thing> stuff; // works!
Container<int> stuff; // doesn't work :(
return 0;
}
编辑:
编译器的错误信息是
prog.cpp: In instantiation of ‘class Container<int>’:
prog.cpp:36:17: required from here
prog.cpp:26:78: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
typename std::enable_if<std::is_base_of<ThingBase, ThingType>::value>::type p()
我不打算让这个方法被重载。我希望终端用户可以随时使用它。这些p
方法中只有一个,它应该只需要一个(相对简单的)签名。
我不打算重载这个方法。我希望终端用户可以随时使用它。这p个方法中只能有一个,并且应该只需要一个(相对简单的)签名。
这大大简化了练习。解决办法是……不做什么特别的事。
void p() {
m_things[0].printHi();
}
当隐式实例化类模板时,只有成员函数的声明与它一起实例化。在尝试使用成员之前,定义不会实例化。
所以你不需要做任何特别的事情。
如果在不能使用的情况下使用,则会出现错误。如果您仍然希望确保可衍生性,并在这种情况下产生描述性错误,则可以在成员函数体中添加static_assert
。只需对条件使用is_base_of
测试,并添加一个漂亮的字符串。
这是编写泛型实用程序时的常用方法。另一方面,SFINAE的主要目的是控制过载分辨率。但你不能在这里做。