我正在尝试实现一个模板类,如果模板参数正确,则该模板类既可以用作派生的基础,又可以用作具体类。
我要实现的是,如果无法实例化模板类的方法,但是派生类提供了一种实现,那就可以了。
但是,如果可以完全实例化该模板,则该类本身就是有效的。
例:
// interface class
class A
{
public:
virtual void foo() = 0;
virtual ~A() {}
};
// template class
template <typename T>
class B : public A
{
public:
/* if this tenplate can be instantiated */
foo()
{
T obj;
std::cout << obj;
}
/* else
foo() = 0;
*/
};
// concrete classes
// will work on it's own
typedef B<std::string> C;
class D : public B<void>
{
// B<void>::foo won't instantiate on it's own
// so we provide help here
foo() {}
};
int main(int argc, char const *argv[])
{
A * = new C(); // all good
A * = new D(); // error: cannot instantiate B<void>::foo
return 0;
}
有没有办法达到这种效果?
最佳答案
使用SFINAE,您可以执行以下操作:
namespace detail
{
// an helper for traits
template <typename T>
decltype(T{}, std::cout << T{}, std::true_type{})
helper_has_default_constructor_and_foo(int);
template <typename T>
std::false_type helper_has_default_constructor_and_foo(...);
// the traits
template <typename T>
using has_default_constructor_and_foo = decltype(helper_has_default_constructor_and_foo<T>(0));
// genaral case (so when traits is false)
template <typename T, typename = has_default_constructor_and_foo<T>>
struct C : public A {};
// specialization when traits is true
template <typename T>
struct C<T, std::true_type> : public A
{
void foo() override { std::cout << T{}; }
};
}
最后:
template <typename T>
class B : public detail::C<T>
{
};
live demo
关于c++ - C++类模板或纯虚拟,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29144397/