2010-07-24 109 views
3

我正在嘗試構建小型記錄器庫。 我是facig C++模板的一些問題。 這是我的課堂結構。C++模板問題

class abstract_logger_t { 
public: 
    typedef abstract_logger_t logger_type; 
    template<typename data_t> 
    abstract_logger_t& log(const data_t& data) { 
    return *this; 
    } 
}; 

class stdout_logger_t : public abstract_logger_t { 
public: 
    typedef stdout_logger_t logger_type; 
    template<typename data_t> 
    stdout_logger_t& log(const data_t& data) { 
    cout << data << endl; 
    return *this; 
    } 
}; 


template<typename logger_t, typename data_t> 
void output(logger_t& logger, const data_t& data) { 
    static_cast<typename logger_t::logger_type&>(logger).log(data); 
    cout << data; 
} 


template<typename data_t> 
abstract_logger_t& operator<< (abstract_logger_t& logger, const data_t& data) { 
    output(logger, data); 
    return logger; 
} 


stdout_logger_t logger; 
logger << "Hi " << 1; 

這裏我期待stdout_logger_t :: log被輸出調用。 但它看起來像派生類型正在丟失 和abstract_logger_t :: log最終被調用。 有人可以告訴我,如果我做錯了什麼?

+0

你爲什麼施放你的記錄器?如果沒有靜態演員,模板不會工作嗎? – josefx 2010-07-24 13:02:31

回答

1
template<typename data_t> 
abstract_logger_t& operator<< (abstract_logger_t& logger, const data_t& data) { 
    output(logger, data); 
    return logger; 
} 

在這裏,你傳遞什麼logger,編譯器將其轉換爲abstract_logger_t&。您還需要製作第一個參數模板。

template<typename T, typename data_t> 
T& operator<< (T& logger, const data_t& data) { 
    output(logger, data); 
    return logger; 
} 
2

沒有必要讓事情比他們應該更復雜。 這裏的遺產是無用的,除非你想使用虛擬方法,在這種情況下,你將不會使用模板。 這裏是你的代碼的更新版本。只需添加其他記錄器類,當你需要新的記錄器類。

class stdout_logger_t 
{ 
public: 
    typedef stdout_logger_t logger_type; 
    template<typename data_t> 
    logger_type& log(const data_t& data) { 
    cout << data << endl; 
    return *this; 
    } 
}; 
class lazy_logger_t 
{ 
public: 
    typedef lazy_logger_t logger_type; 
    template<typename data_t> 
    logger_type& log(const data_t& data) { 
    return *this; 
    } 
};  
template<typename logger_t, typename data_t> 
void output(logger_t& logger, const data_t& data) { 
    logger.log(data); 
} 
template<typename logger_t, typename data_t> 
logger_t& operator<< (logger_t& logger, const data_t& data) { 
    output(logger, data); 
    return logger; 
} 

stdout_logger_t logger; 
lazy_logger_t lazyLogger; 
logger << "Hi " << 1; 
lazyLogger << "Hi " << 1; 

要小心,我非常確定這個記錄系統不能用於std :: endl。

+1

另外,這將在'_'鏈中的__every__表達式之後放置一個'std :: endl'。所以'logger <「Hi」<< 1;'會導致在單獨的行上發出「Hi」和「1」。 – sbi 2010-07-26 09:07:31

0

看來你是混淆模板與運行時多態性。另外,您的abstract_logger_t類不是抽象的。你使用logger_t = abstract_logger_t從運營商< <輸出輸出。模板參數是通過檢查靜態類型而不是動態類型來確定的。模板參數推導和模板實例化是編譯時機制。這應該回答你的問題。

BTW:約定是使用CamlCase名稱作爲模板參數。

+0

Err ..誰的約定?當然不是我的.... – 2010-07-24 14:31:40