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

}

一种方法是使用 va_list。有没有办法我可以通过一个类来完成这个?

谢谢

4

1 回答 1

3

我猜你几乎在那里:

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

这应该做你想要的。但是请注意,T最后两个参数使用相同,因此此函数调用将无法推断T

setData("some_float_value", valTwo, 0.05); 

因为0.05是 a double,whilevalTwo是浮点数。在类型推导期间,不会执行类似的转换,因为编译器正在尝试匹配确切的类型。

不过,这很容易解决:

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

f后缀使最后一个参数是类型的纯右值,float因此T可以推导出为float


可能,您可能希望第二个和第三个参数允许不同的类型,只要第三个可以转换为第二个即可。在这种情况下,您可以重新定义函数模板,如下所示:

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

但是,请注意,这将使您可以自由地setData()使用任何两种类型T和进行实例化U,而您可能希望您的模板仅针对U可转换为Ts 的 s 进行实例化。一些 SFINAE 技巧与std::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 回答