[英]C++ template instantiation restrictions
我在類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將被調用(取決於something())。 但是,編譯器堅持實例化foo_1和foo_2,因為兩者都可以被調用。
這給T提供了一個必須提供bar方法的負擔。
我如何告訴編譯器以下內容:
您可以使用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();
}
您可以為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方法的所有類型的某些東西或修改所有這些支持條的類型,以便它們共享一些可以在編譯時確定的共同點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.