13

C++で関数戻り型のオーバーロードをモックする方法を見つける必要があります。

それを直接行う方法がないことは知っていますが、すぐに使える方法があることを願っています。ユーザーが作業するためのAPIを作成しており、文字列情報に基づいて値を取得するデータ文字列を渡します。これらの値は異なるタイプです。本質的に、私たちは彼らに次のことをさせたいと思います。

int = RetrieveValue(dataString1);
double = RetrieveValue(dataString2);
// Obviously, since they don't know the type, they wouldn't use int =.... It would be:
AnotherFunction(RetrieveValue(dataString1)); // param of type int
AnotherFunction(RetrieveValue(dataString2)); // param of type double

しかし、それはC ++では機能しません(明らかに)。現在、次のように呼ばれるように設定しています。

int = RetrieveValueInt(dataString1);
double = RetrieveValueDouble(dataString2);

ただし、データ文字列のタイプを知っている必要はありません。

残念ながら、外部ライブラリの使用は許可されていないため、Boostを使用することはできません。

これを回避する方法はありますか?

明確にするために、私はC++がネイティブにそれを行うことができないことを理解しています。しかし、それを回避する方法が必要です。たとえば、RetrieveValue(dataString1、GetType(dataString1))を実行することを考えました。GetTypeも1つのリターンタイプしか持てないため、これで実際に修正されることはありません。しかし、私はそのようなものが必要です。

私はこの質問が以前に尋ねられたことを理解していますが、別の意味で。明白な答えはどれも使えません。それが私にとって有用であるためには、完全に箱から出してすぐに使えるものが必要ですが、他の質問の回答には当てはまりませんでした。

4

10 に答える 10

29

これから始めなければなりません:

template<typename T>
T RetrieveValue(std::string key)
{
     //get value and convert into T and return it
}

この関数をサポートするには、値を type に変換するためにもう少し作業する必要がありますT。値を変換する簡単な方法は次のとおりです。

template<typename T>
T RetrieveValue(std::string key)
{
     //get value
      std::string value = get_value(key, etc);

      std::stringstream ss(value);
      T convertedValue;
      if ( ss >> convertedValue ) return convertedValue;
      else throw std::runtime_error("conversion failed");
}

この関数を次のように呼び出す必要があることに注意してください。

int x = RetrieveValue<int>(key);

int代わりにこれを行うことができれば、2 回言及することを避けることができます。

Value RetrieveValue(std::string key)
{
     //get value
      std::string value = get_value(key, etc);
      return { value };
}

whereValueは次のように実装されます。

struct Value
{
    std::string _value;

    template<typename T>
    operator T() const   //implicitly convert into T
    {
       std::stringstream ss(_value);
       T convertedValue;
       if ( ss >> convertedValue ) return convertedValue;
       else throw std::runtime_error("conversion failed");
    }
}

次に、これを書くことができます:

int    x = RetrieveValue(key1);
double y = RetrieveValue(key2);

どれが欲しいですか?

于 2013-02-12T19:29:29.157 に答える
2

これを行う唯一の適切な方法は、戻り値をパラメーターに移動することです。

 void retrieve_value(std::string s, double& p);
 void retrieve_value(std::string s, int& p);
 <...>

 double x;
 retrieve_value(data_string1, x);

 int y;
 retrieve_value(data_string2, y);
于 2013-02-12T19:33:32.733 に答える
2

オーバーロードであろうと特殊化であろうと、情報が関数シグネチャに含まれている必要があります。未使用の 2 番目の引数として変数を渡すことができます。

int RetrieveValue(const std::string& s, const int&) {
  return atoi(s.c_str());
}
double RetrieveValue(const std::string& s, const double&) {
  return atof(s.c_str());
}

int i = RetrieveValue(dataString1, i);
double d = RetrieveValue(dataString2, d);
于 2013-02-12T19:37:17.353 に答える
1

値がゼロや負になることは決してないことがわかっている場合は、int と double を保持する構造体を返し、必要のないものをゼロにします...

安くて汚いですが、簡単な方法です...

struct MyStruct{
int myInt;
double myDouble;
};

MyStruct MyFunction(){
}
于 2013-02-12T19:31:19.160 に答える
0

残念ながら、関数の戻り値の型をオーバーロードする方法はありません。この回答を参照してください。 戻り値の型によるオーバーロード

于 2013-02-12T19:30:31.877 に答える
0
int a=itoa(retrieveValue(dataString));
double a=ftoa(retrieveValue(dataString));

どちらも文字列を返します。

于 2013-02-12T19:30:38.800 に答える
0

テンプレート ソリューションの代わりに、関数でクラスへの参照またはポインターを返すようにし、そのクラスのサブクラスを作成して、返したいさまざまなデータ型を含めることができます。RetrieveValue次に、適切なサブクラスへの参照を返します。

これにより、ユーザーは、返されたオブジェクトが属するサブクラスを知らなくても、返されたオブジェクトを他の関数に渡すことができます。

この場合の問題は、メモリ管理の 1 つになります。つまり、どの関数が返されたオブジェクトを割り当て、どの関数がそれを削除するか、そしてメモリ リークを回避する方法をいつ選択するかです。

于 2013-02-12T19:31:45.450 に答える
-2

あなたが実際に望んでいたものではない例を使用したため、みんなを少し失望させました.

関数呼び出しはコンパイル時に解決されるため、実際のセットアップ (戻り値の型が不明なこの関数の戻り値で関数を呼び出す) は機能しません。

その後、ランタイム ソリューションに制限されます。訪問者パターンをお勧めします。この変更を可能にするには、設計を大幅に変更する必要があります。私が見ることができる別の方法はありません。

于 2013-02-12T19:54:20.107 に答える