簡體   English   中英

C ++模板實例化限制

[英]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方法的負擔。

我如何告訴編譯器以下內容:

  • 如果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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM