我有一个基类Base
,许多其他类将派生自。我想定义:
template<typename Derived>
ostream &operator<< (ostream &o, Derived &derived) {
}
但仅适用于从Base
派生的类。我需要将之前定义的所有operator<<
用于其他类型。怎么做?那可能吗?
我无法创建ostream &operator<< (ostream &o, Base &base)
,因为我需要在某些类型特征中使用的确切类型。在将值作为基类型传递时,有没有办法“推”派生类型?
答案 0 :(得分:6)
http://www.boost.org/doc/libs/1_46_0/libs/utility/enable_if.html
template<typename Derived>
typename enable_if<is_base_of<Base, Derived>, ostream&>::type
operator<< (ostream &o, Derived &derived)
{
}
答案 1 :(得分:2)
您可以使用类型特征和SFINAE只允许从Base派生的类进入您的函数:
#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
struct Base {};
template<typename Derived>
typename boost::enable_if<boost::is_base_and_derived<Base, Derived>, std::ostream&>::type
operator<<(std::ostream& o, Derived& derived);
struct A : Base {};
struct B : Base {};
struct C {};
int main()
{
A a;
B b;
C c;
std::cout << a << '\n'; // compiles
std::cout << b << '\n'; // compiles
std::cout << c << '\n'; // error: no match for 'operator<<' in 'std::cout << c'
}
答案 2 :(得分:2)
另一种选择是从标记模板派生
struct Base { /* ... */ };
template<typename T>
struct BaseOutputtable {
T *getDerived() {
return static_cast<T*>(this);
}
T const *getDerived() const {
return static_cast<T const*>(this);
}
protected:
~BaseOutputtable() { }
};
然后从两个派生出来
struct MyDerived : Base, BaseOutputtable<MyDerived> {
/* ... */
};
现在你可以把它写成
template<typename Derived>
ostream &operator<< (ostream &o, BaseOutputtable<Derived> &derived) {
/* ... */
}
这样做的好处是它的简单性。如果Base
已被模板化,则更有用(我认为这不是您的代码的情况)。
答案 3 :(得分:1)
您可以使用is_base_of
类模板来确保只有Base
的派生类可以调用operator<<
:
template<typename Derived>
ostream &operator<< (ostream &o, Derived &derived)
{
static_assert<is_base_of<Base, Derived>::value>();
}
您可以在stackoverflow本身的另一个主题中找到is_base_of
的定义:click here
以下是static_assert
:
template<bool> struct static_assert;
template<> struct static_assert<true> {};