0

私は次の行に沿って何かを書こうとしています:

void setData<T>(char * environmentVariable, T &data, T defaultValue)
{
    bool ret = false;
    // Try to get the environmentVariable
    ret = handle.getParam(environmentVariable, data);
    if(!ret)
    {
        data = defaultValue
    }
}

int main()
{
    int valOne;
    float valTwo;

    // Get a value of type int
    setData("some_int_value", valOne, 10);  // 10 is the default value

    // Get a value of type float
    setData("some_float_value", valTwo, 0.05f);  // 0.05 is the default value

}

これを行う 1 つの方法は、va_list を使用することです。クラスでこれを達成する方法はありますか?

ありがとう

4

1 に答える 1

3

私はあなたがほとんどそこにいたと思います:

template<typename T>
void setData(char * environmentVariable, T &data, T defaultValue)
{
    // ...
}

これはあなたが望むことをするはずです。ただし、最後の 2 つの引数には同じものTが使用されることに注意してください。したがって、この関数呼び出しでは次のように推測できなくなりTます。

setData("some_float_value", valTwo, 0.05); 

0.05は であるためdoublevalTwoはフロートです。型推定中、コンパイラは正確な型を一致させようとしているため、同様の変換は実行されません。

ただし、これは簡単に修正できます。

setData("some_float_value", valTwo, 0.05f); 
//                                      ^

接尾辞により、最後のf引数は 型の prvalue にfloatなるため、 であるTと推測できますfloat


3 番目の引数を 2 番目の引数に変換できる限り、2 番目と 3 番目の引数に異なる型を許可したい場合があります。この場合、関数テンプレートを次のように再定義できます。

template<typename T, typename U>
void setData(char * environmentVariable, T &data, U defaultValue)
{
    // ...
}

setData()ただし、これにより、任意の 2 つのタイプTおよびでインスタンス化する自由が得られることに注意してください。ただし、 に変換可能な sUに対してのみテンプレートをインスタンス化することをお勧めします。型特性と組み合わせたいくつかの SFINAE トリックが仕事をします:UTstd::is_convertible<>

#include <type_traits>

template<typename T, typename U,
         typename std::enable_if<
             std::is_convertible<U, T>::value
             >::type* = nullptr>
void setData(char * environmentVariable, T &data, U defaultValue)
{
    // ...
}

これで、コンパイラ エラーが発生することなく、元の呼び出しを使用することもできます。

setData("some_float_value", valTwo, 0.05); 
//                                  ^^^^
于 2013-03-21T00:26:16.510 に答える