我在C类中有一个方法foo,它调用foo_1或foo_2。 这个方法foo()必须在C中定义,因为foo()在BaseClass中是纯虚拟的,实际上我是 必须制作C型对象。代码如下:
template <class T>
class C:public BaseClass{
void foo() {
if (something()) foo_1;
else foo_2;
}
void foo_1() {
....
}
void foo_2() {
....
T t;
t.bar(); // requires class T to provide a method bar()
....
}
};
现在对于大多数类型来说,T foo_1就足够了,但是对于某些类型,将会调用foo_2 (取决于某事())。但是编译器坚持要实例化foo_1 和foo_2因为可能被调用。
这给它必须提供的T带来了负担 一种酒吧方法。
如何告诉编译器:
答案 0 :(得分:1)
您可以使用boost.enable_if
。像这样的东西:
#include <boost/utility/enable_if.hpp>
#include <iostream>
struct T1 {
static const bool has_bar = true;
void bar() { std::cout << "bar" << std::endl; }
};
struct T2 {
static const bool has_bar = false;
};
struct BaseClass {};
template <class T>
class C: public BaseClass {
public:
void foo() {
do_foo<T>();
}
void foo_1() {
// ....
}
template <class U>
void foo_2(typename boost::enable_if_c<U::has_bar>::type* = 0) {
// ....
T t;
t.bar(); // requires class T to provide a method bar()
// ....
}
private:
bool something() const { return false; }
template <class U>
void do_foo(typename boost::enable_if_c<U::has_bar>::type* = 0) {
if (something()) foo_1();
else foo_2<U>();
}
template <class U>
void do_foo(typename boost::disable_if_c<U::has_bar>::type* = 0) {
if (something()) foo_1();
// I dunno what you want to happen if there is no T::bar()
}
};
int main() {
C<T1> c;
c.foo();
}
答案 1 :(得分:0)
您可以为foo_1和foo_2创建一个界面,例如:
class IFoo
{
public:
virtual void foo_1()=0;
virtual void foo_2()=0;
};
template <typename T>
class C : public BaseClass, public IFoo
{
void foo()
{
if (something())
foo_1();
else
foo_2();
}
};
template <typename T>
class DerivedWithBar : C<T>
{
public:
void foo_1() { ... }
void foo_2()
{
...
T t;
t.bar(); // requires class T to provide a method bar()
...
}
};
template <typename T>
class DerivedNoBar : C<T>
{
public:
void foo_1() { ... }
void foo_2() { ... }
};
答案 2 :(得分:0)
我认为最简单的方法是简单地编写一个'C'可以调用的单独的函数模板:
template <class T>
void call_bar(T& /*t*/)
{
}
template <>
void call_bar<Something>(Something& t)
{
t.bar();
}
原始的'C'类可以相应地修改:
void foo_2() {
....
T t;
call_bar(t); // does not require T to provide bar()
....
}
这有一个缺点,你必须明确定义哪些类型的T提供bar方法,但这几乎是不可避免的,除非你可以在编译时确定在公共接口中提供bar方法的所有类型的东西或修改所有这些条形支持类型,以便它们共享可在编译时确定的共同点。