仅为从单个基础派生的类定义模板函数

时间:2011-02-24 18:11:49

标签: c++ templates

我有一个基类Base,许多其他类将派生自。我想定义:

template<typename Derived>
ostream &operator<< (ostream &o, Derived &derived) {
}

但仅适用于从Base派生的类。我需要将之前定义的所有operator<<用于其他类型。怎么做?那可能吗?

我无法创建ostream &operator<< (ostream &o, Base &base),因为我需要在某些类型特征中使用的确切类型。在将值作为基类型传递时,有没有办法“推”派生类型?

4 个答案:

答案 0 :(得分:6)

http://www.boost.org/doc/libs/1_46_0/libs/utility/enable_if.html

http://www.boost.org/doc/libs/1_42_0/libs/type_traits/doc/html/boost_typetraits/reference/is_base_of.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> {};