C ++模板实例化限制

时间:2010-06-30 17:37:59

标签: c++ templates instantiation

我在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带来了负担 一种酒吧方法。

如何告诉编译器:

  • 如果T没有bar(),还是允许它作为实例化类型吗?

3 个答案:

答案 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方法的所有类型的东西或修改所有这些条形支持类型,以便它们共享可在编译时确定的共同点。