2

boost::any最初にテンプレートを使用して任意のタイプを印刷できる印刷機能を作成する方法を見つけるのに苦労しています。

template <typename T>
struct printer {
    void print(ostream& os, const boost::any& a);
}; 

最初に を定義する必要がありますprint()。私は任意のものを実数にしたいと思っています。アイデアは簡単です。適切な T を持つoperator <<クラスのインスタンスを各任意のオブジェクトにアタッチし 、値の型が変更されたときにこのオブジェクトを変更します。最初の技術的な問題は、プリンター オブジェクトが T に依存しているのに対し、any はクラス テンプレートではない (また、そうであってはならない) ことです。printer<T>any

今夜か明日のために本当に手を貸してください明日の締め切りがありますが、今夜それを処理したいと思います。

4

4 に答える 4

2

「 C++ 標準ライブラリを超えて: Boost の紹介」で説明されているように、これを行うには非常に簡単な方法があります。

struct streamer {
  virtual void print(ostream &o, const boost::any &a) const =0;
  virtual streamer * clone() const = 0;
  virtual ~streamer() {}
};

template <class T>
struct streamer_impl: streamer{
  void print(ostream &o, const boost::any &a) const { o << *boost::any_cast<T>(a); }
  streamer *clone() const { return new streamer_impl<T>(); }
};

class any_out {
  streamer *streamer_;
  boost::any o_;
  void swap(any_out & r){
    std::swap(streamer_, r.streamer_);
    std::swap(o_, r.o_);
  }
public:
  any_out(): streamer_(0) {}
  template<class T> any_out(const T& value)
    : streamer_(new streamer_impl<T>()), o_(value) {}
  any_out(const any_out& a)
    : streamer_(a.streamer_ ? a.streamer_->clone() : 0), o_(a.o_) {}

  template <class T>
  any_out & operator=(const T& r) { 
    any_out(r).swap(*this);
    return *this;
  }
  ~any_out() { delete streamer_; }

  friend std::ostream &operator<<(std::ostream& o, const any_out & a) {
    if(a.streamer_)
      a.streamer_->print(o, a);
    return o;
  }
};

any_outの代わりに使用しますboost::any

于 2011-02-13T17:25:50.470 に答える
1

私はこれを次のように行います。これはクリーンで安全だと思います。

any_extension.hpp:

namespace cpputil
{

struct AnyWriter
{
    /// Register a type with the AnyWriter.
    /// @pre T must have an ostream << operator available somewhere
    template<class T> static bool registerType()
    {
        return registeredTypes().emplace(std::type_index(typeid(T)),
                                         std::bind(&AnyWriter::write<T>,
                                                   std::placeholders::_1,
                                                   std::placeholders::_2)).second;
    }

    /// Write any registred object to a stream
    /// @pre Underlying type must have been registered with a call to AnyWriter::registerType<T>
    /// @param os is reference to a std::ostream
    /// @param anyObject is a reference to a boost::any
    static void writeAny(std::ostream& os, const boost::any& anyObject);
private:

    // A function object that converts an any to a type and streams it to an ostream
    using WriteFunction = std::function<void (std::ostream&, const boost::any&)>;

    // a map of typeinfo to WriteFunction
    using RegisteredTypes = std::unordered_map<std::type_index, WriteFunction >;

    // retrieve the WriteFunction map in a safe way
    static RegisteredTypes& registeredTypes();

    // Convert an any to a type, and write it to a stream
    template<class T> static void write(std::ostream& os, const boost::any& anyObject) {
        try {
            const T& typedObject = boost::any_cast<const T&>(anyObject);
            os << typedObject;
        }
        catch(boost::bad_any_cast& e) {
            os << "<exception in conversion: " << e.what() << ">";
        }
    }

};
}

namespace std {
    ostream& operator<<(ostream& os, const ::boost::any& anyObject);
}

any_extension.cpp:

#include "any_extension.h"
#include <string>

namespace cpputil {

namespace AnyWriterRegistration {
    const bool stringRegistered = AnyWriter::registerType<std::string>();
    const bool intRegistered = AnyWriter::registerType<int>();
    const bool doubleRegistered = AnyWriter::registerType<double>();
}



AnyWriter::RegisteredTypes& AnyWriter::registeredTypes()
{
    static RegisteredTypes _registrationMap;
    return _registrationMap;
}

void AnyWriter::writeAny(std::ostream &os, const boost::any &anyObject)
{
    auto registered = registeredTypes();
    auto iFind = registered.find(anyObject.type());
    if(iFind == registered.end()) {
        os << "<unregistered type: " << anyObject.type().name() << ">";
    }
    else {
        iFind->second(os, anyObject);
    }
}

}

namespace std {
ostream& operator<<(ostream& os, const ::boost::any& anyObject)
{
    if(anyObject.empty()) {
        os << "<empty>";
    }
    else {
        cpputil::AnyWriter::writeAny(os, anyObject);
    }
    return os;
}
}

サポートしたい型については、その型に対して AnyWriter::register() が呼び出され、その型に対して operator<< が存在することを確認してください。

例えば:

any_test.cpp:

struct chicken {};
std::operator<<(std::ostream& os, const chicken& aChicken) {
    os << "cluck!";
    return os;
}

namespace {
    const bool chickenRegistered = AnyWriter::register<Chicken>();
}

void chickenTest() {
    boost::any animal = chicken();
    std::cout << animal << std::endl;
}

出力: カチャッ!

于 2013-10-15T11:55:28.380 に答える
0

Boostメーリングリストでこのスレッドをチェックしてください:http: //lists.boost.org/Archives/boost/2005/01/79232.php

それにはいくつかのアイデアがあり、そのうちのいくつかはある種のOKのように見え、いくつかは(私には)そうではありません。ただし、全体として、これは一般的な方法で実行するのが難しいタスクのように見えます。これは、(そのスレッドで言及されているように)一部のタイプは決してostreamできないが、boost::anyオブジェクトに含まれている可能性があるためです。

于 2011-02-13T16:53:24.197 に答える