0

std :: mapで正しい変数を見つけて返すために、std::stringを受け取る単一のgettemplateメソッドを持つクラスを作成したいと思います。

std :: mapは任意のタイプの変数を格納する必要があるため、boost :: anyを使用しました。これまでのところ、std::mapは次のようになっています。

std::map<std::string, boost::any> variables_;

get関数については、次のようなものを試しました。

template <typename T>
T get(std::string& parameter)
{
    return variables_[parameter];
}

しかし、幸運なことではありません、私の質問は、それも可能ですか?もしそうなら、どのように?

基本的な考え方は、クラス内のすべての特定の変数に特定のメソッドを作成したくないので、他のクラスはそのすべてのgetメソッドについて知る必要がないということです。

ありがとう!

ps:なぜこれが欲しいのかと尋ねる人のために、ここに履歴書があります。私にはたくさんのアルゴリズムがあり、特定の順序で実行され、最後に実行されたアルゴリズムにそれを使用します。だから、私が欲しいのは、どのアルゴリズムが実行されるか、どの順序で、どのデータを別のアルゴリズムから使用するかを示すxmlファイルを作成することです。

したがって、たとえば、アルゴリズムAには「threshold」という名前の変数があり、アルゴリズムBはその情報を必要とするため、通常はA.getThresholdなどを使用してAに問い合わせる必要がありますが、私が知る限り、 (xmlファイルから)文字列内の名前でオブジェクト関数を呼び出すので、私のソリューションには、必要な変数名を渡すget関数のみが含まれ、その関数はそれを返します。

4

4 に答える 4

2

別の解決策は、オブジェクトを別のオブジェクトに「ラップ」するboost::anyことです。このオブジェクトは、必要なものに自動的に変換できます。それは良い習慣ではないと思いますが、あなたの質問によるとそれは最適です。

class AnyWrapper {
    boost::any value;
public:
    AnyWrapper(const boost::any& val) : value(val) {}
    template<typename T> operator T() {
        return boost::any_cast<T>(value);
    }
}

そして、あなたのゲッターは次のようになります:

AnyWrapper get(std::string& parameter)
{
    return variables_[parameter];   // variables is a std::map<std::string, boost::any> 
}

そして、あなたはそのようなあなたの要素を取得することができるはずです:

int integerValue = myContainer.get("age");
std::string stringValue = myContainer.get("name");

しかし、繰り返しになりますが、これはクリーンなソリューションではありません。ブーストの作者がany_castを明示的にすることを選んだ理由があります:)

于 2012-06-11T20:04:06.343 に答える
1

boost::any値は暗黙的に型に変換されません。T手動でキャストを要求する必要があります。

template <typename T>
T get(std::string& parameter)
{
    return boost::any_cast<T>(variables_[parameter]);
}

boost::bad_any_castに格納されているタイプが正確anyにではない場合、呼び出しは例外を除いて失敗します。 T

于 2012-06-11T19:47:17.970 に答える
0

を返すこともできますboost::any。実装のカプセル化は失われますが、戻り値の使用方法によっては、それがより良い方法である可能性があります。

于 2012-06-11T19:48:36.027 に答える
0

コンパイル時(テンプレート)と実行時(マップルックアップ)のコードを混在させようとしているため、必要なことはできません。

完全にランタイムにする必要があります。

struct base_type { virtual ~base_type{} };
struct derived_type: base_type { ... };
std::map<std::string, base_type*> lookup_map;
base_type* get(std::string const& key) { return lookup_map[key]; }

または、完全にコンパイルする時間(boost.fusionの例):

#include <boost/fusion/container/map.hpp>
#include <boost/fusion/sequence/intrinsic/at_key.hpp>
#include <boost/fusion/sequence/intrinsic/value_at_key.hpp>

namespace bf=boost::fusion;

struct key_a; // analogues of string keys in compile time world
struct key_b;
struct key_c;

typedef bf::map<
  bf::pair<key_a, long>,
  bf::pair<key_b, double>,
  bf::pair<key_c, char const*>
> rtmap_t;
rtmap_t rtmap;

template <class Key>
void set_value(typename bf::result_of::value_at_key<rtmap_t, Key>::type const& val)
{
  bf::at_key<Key>(rtmap) = val;
}

template <class Key>
typename bf::result_of::at_key<rtmap_t, Key>::type get_value()
{
  return bf::at_key<Key>(rtmap);
}

#include <iostream>
int main()
{
  char const* cval = "hello metaprogramming";
  set_value<key_a>(123l);
  set_value<key_b>(456.789);
  set_value<key_c>(cval);
  std::cout << get_value<key_a>() << std::endl;
  std::cout << get_value<key_b>() << std::endl;
  std::cout << get_value<key_c>() << std::endl;

  return 0;
}

あなたがあなたの質問で提供した情報を考慮して、私は動的ポリモーフィズムを備えたランタイムバリアントを選択します。

于 2012-06-11T20:27:15.080 に答える