C++模板实例化限制
我在类C中有一个方法foo,它可以调用foo_1或foo_2。 该方法foo()具有在C被定义,因为FOO()是纯在BaseClass的虚拟和我实际上 必须进行以下类型C.代码的对象: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()
....
}
};
现在大多数类型ŤFOO_1将足够,但对于某些类型foo_2将被称为 (取决于())。然而,编译器坚持要实例化foo_1 和foo_2,因为可能会调用它们。
这给T带来了负担,它必须提供条形方法 。
我如何告诉编译如下:
- 如果T没有吧(),仍然允许它作为一个实体化类型?
您可以使用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();
}
我们可以做到这一点,而不使用提升? – user231536 2010-06-30 17:54:01
请参阅http://stackoverflow.com/questions/2937425/boostenable-if-class-template-method/2937522#2937522 - 你需要templatize“do_foo” – 2010-06-30 17:54:22
你是对的,我正在寻求适当的解决方案: - )。 – 2010-06-30 17:58:58
您可以为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() { ... }
};
我认为最简单的方法是简单地写一个单独的函数模板“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方法的所有类型的东西或者修改所有这些条形支撑类型,以便它们共享可以在编译时确定的共同事物。
“这有一个缺点,你必须明确定义哪种类型的T提供了一个bar方法,但这几乎是不可避免的,除非你可以在编译时确定在公共接口中提供一个bar方法的所有类型的东西”你可以强迫所有人在他们的公共界面中定义这样一个功能。 ADL [尊重和发现](http://www.gotw.ca/publications/mill02。htm)在这些类型的命名空间中定义的函数。请参阅解释“接口原则”的链接。如果我想用一个免费的功能,我会将它基于ADL。 – 2010-06-30 18:09:56
@Johannes根据OP的说法,something()不是可以在运行时评估的表达式。如果没有更多的上下文信息,我们不得不假设调用foo_1和foo_2(期望栏的代码)的代码将针对所有类型生成。T我们如何利用ADL来处理这种情况?有一个函数call_bar,它不会在调用bar的单独命名空间中调用bar,将bar中的类型放在不同的命名空间中,并依赖于ADL来调用正确的版本? – stinky472 2010-06-30 23:11:26
我的意思是foo()在BaseClass中是纯虚拟的。 – user231536 2010-06-30 17:43:42
@andand他的班名是'C'。我不认为他指的是C语言。 – stinky472 2010-06-30 17:44:00
什么是'something()'?它是否有一些编译时常量? – 2010-06-30 17:48:12