19

パッケージに含まれる Map std::map<std::string, boost::any>があります。boost::program_options次に、そのマップのコンテンツを印刷したいと思います。

for(po::variables_map::const_iterator it = vm.begin(); it != vm.end(); ++it) {
  std::cerr << it->first << ": " << it->second << std::endl;
}

残念ながら、定義されboost::anyていないため、それは不可能です。operator<<

その地図を印刷する最も簡単な方法は何ですか?

anyそれぞれを int、次に double、次に string などに自動的にキャストしようとする独自の出力演算子を定義できます。毎回エラーを無視し、キャストが成功して指定された型として出力できるようになるまでキャストを試みます。

しかし、ブーストにはもっと簡単な方法があるはずですか? 私は逆のようなものが必要だろうlexical_cast...

4

9 に答える 9

30

代わりに使用できますboost::spirit::hold_any。ここで定義されています:

#include <boost/spirit/home/support/detail/hold_any.hpp>

と完全に互換性がありboost::anyます。と比較すると、このクラスには 2 つの違いがありboost::anyます。

  • スモール オブジェクト最適化イディオムと他のいくつかの最適化トリックを利用して、spirit::hold_anyより小さく高速にします。boost::any
  • ストリーミング演算子 (operator<<()およびoperator>>()) が定義されているため、シームレスに入出力できますspirit::hold_any

唯一の制限は、空の に入力できないことですがspirit::hold_any、入力から期待される型の (おそらくデフォルトで構築された) インスタンスを保持する必要があります。

于 2010-07-12T00:39:29.287 に答える
5

boost::any別のタイプに変更できる場合は、 Boost.TypeErasureを使用できます。のような型を作成したいがany、コンパイル時にこれらの特定の操作をサポートする型のみをサポートする場合は、これが最適です。

#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/any.hpp>
#include <boost/mpl/vector.hpp>
#include <random>
#include <iostream>

namespace te = boost::type_erasure;

typedef te::any<boost::mpl::vector<
    te::copy_constructible<>,
    te::destructible<>,
    te::ostreamable<>
>> streamable_any;

int main()
{
    streamable_any i(42);
    streamable_any d(23.5);
    std::mt19937 mt;
    streamable_any r(mt);
    std::cout << i << "\n" << d << "\n" << r << "\n";
}

Live On Coliru

于 2016-06-23T22:13:35.093 に答える
3

残念ながら、anyを使用する唯一の方法は、type()メソッドを使用してanyに何が含まれているかを判断し、それをany_castでキャストすることです。明らかに、RTTI を有効にする必要がありますが、いずれかを使用している場合は、おそらく既に有効になっています。

for(po::variables_map::const_iterator it = vm.begin(); it != vm.end(); ++it) {
  if(typeid(float) == it->second.type()) {
      std::cerr << it->first << ": " << any_cast<float>(it->second) << std::endl;
  }
  else if(typeid(int) == it->second.type()) {
      std::cerr << it->first << ": " << any_cast<int>(it->second) << std::endl;
  }
  ...
}
于 2010-07-11T23:34:44.563 に答える
0

xany を使用してみてください https://sourceforge.net/projects/extendableany/?source=directory xany クラスを使用すると、既存の機能に新しいメソッドを追加できます。ちなみに、ドキュメントには、まさにあなたが望むことをする例があります。

于 2012-12-21T20:19:17.337 に答える
0

印刷する必要があるオブジェクトの考えられるケースをすべてカバーする必要があると思います...またはboost::variantを使用してください。

編集:申し訳ありませんが、私はWHYを書くと思っていました.

私がそう思う理由は、どのソース コードを見ても、データを挿入および取得するときに、YOU が型を提供するという事実に依存しているように見えるからです。挿入すると、データはコンパイラによって自動的に検出されるため、指定する必要はありません。ただし、データを取得するときは、取得するデータ型がわからないため、any_cast を使用する必要があります。

それが別の方法で機能し、データ型が確実であれば、 any_cast は必要ないと思います:)

代わりに、バリアントには可能なデータ型のセットが制限されており、この情報はある程度登録されているため、バリアント コンテナーを一般的な方法で反復処理できます。

この種の操作 (一般的な値のセットの反復) が必要な場合は、バリアントを使用する必要があると思います。

于 2010-07-11T23:03:12.893 に答える