2010-07-24 111 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