2015-12-11 79 views
0

我也看到,它已經在這裏問: C++: Template Parameter Cyclic Dependency模板參數循環依賴

但我不太明白接受的答案在那裏。

因此,讓我重申這裏的問題。

比方說,我有:

template <class P> 
class Consumer { 
    P m_producer; 
public: 
void consume(char* data, uint32_t length) { 
    if (/* some error condition */) { 
     m_producer.errorCallback(); 
    } 
} 
} 

template <class C> 
class Producer { 
    C m_consumer; 
void produce() { 
    char* someData; 
    uint32_t length; 
    m_consumer.consume(someData, length); 
} 
} 

// Pseudocode -- not valid C++. 
Producer<Consumer> c; 
Consumer<Producer> p; 

正如你可以看到,生產者需要調用消費者,和消費者需要調用生產者;並且兩者都依賴於其他模板參數。

不使用任何虛擬類(接口)來解決這種模板參數的最佳方法是什麼?

在此先感謝。

+0

一個需要在另一個之前創建,並將其作爲參考傳遞給另一個,將其作爲指針存儲。 – Simple

+0

爲什麼消費者是生產者的模板參數?你真的想要一個只能爲特定消費者生產東西的生產者嗎?一旦你放棄這個限制,就再也沒有圈子了。 – user463035818

+0

@ tobi303因爲我有不同的消費者,我想避免虛擬表 – Hei

回答

1

與任何這類概念問題一樣,答案是:重構,重構,重構。循環模板參數依賴性指示業務邏輯中的概念性錯誤。

考慮一下將大致是內存佈局,如果這種相關性在那裏接受:

// Not C++ 

Producer a { 
    m_consumer { 
    m_producer { // Not 'a', this is another producer. 
     m_consumer { // With an also different consumer inside. 
     // ... and it continues forever. 
     } 
    } 
    } 
} 

相反,讓我們diferently想想:如果我們只需要一個消費者和一個生產者連接在一起,它不僅使意識到它們是同一個數據結構的一部分。我們可以使用奇異遞歸模板模式,以避免生產商的模板參數:

#include <iostream> 

template<typename Producer> 
class Consumer { 
    Producer& p; 
public: 
    bool error{false}; 
    Consumer(Producer& p_) 
     :  p(p_) 
    {} 
    void consume(char* data, size_t lenght) { 
    if (!data) { 
     p.error_callback(); 
     error = true; 
    } 
    } 
}; 

class Producer : public Consumer<Producer>{ 
public: 
    Producer() 
     : Consumer<Producer>(*this) 
    {} 
    Consumer<Producer>& consumer() {return *this;} 
    void produce() { 
    char* some_data(nullptr); 
    int length{0}; 
    consume(some_data, length); 
    } 
    void error_callback() { 
    std::cout << "Error\n"; 
    } 
}; 

int main() { 
    Producer producer; 
    auto& consumer = producer.consumer(); 
    producer.produce(); 
    if (consumer.error) { 
    std::cout << "Got error from consumer"; 
    } 
} 

讓我們考慮的main()的兩個第一線的內存佈局:

// Not C++ 
Producer a { 
    consumer { // A producer implicitly has a consumer, since it inherits from it. 
    reference to a; 
    } 
} 
reference to consumer; 

當然,這隻解決你陳述的問題。但真正的教訓是:嘗試考慮您期望的內存佈局,這將幫助您找出如何在代碼中表達它。

+0

瞭解了很多(特別是好奇的循環模板,雖然它不是我可以用在我的問題,它有一些有趣的特點)。感謝您的輸入! – Hei

+0

實際上,有一個有趣的解決方案http://qscribble.blogspot.com/2008/06/circular-template-references-in-c.html不確定在C++ 11中是否有更好的方法來實現這一點和C++ 14現在可用。 – Hei