Я пытаюсь написать что-то вроде следующего:
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. Есть ли способ, которым я могу сделать это с помощью класса?
Спасибо
Я думаю, вы были почти там
template<typename T>
void setData(char * environmentVariable, T &data, T defaultValue)
{
// ...
}
Это должно делать то, что вы хотите. Обратите внимание, однако, что то же самое T
используется для последних двух аргументов, поэтому этот вызов функции сделает невозможным вывод T
:
setData("some_float_value", valTwo, 0.05);
Так как 0.05
это double
, в то время как valTwo
это поплавок. Во время вывода типа подобное преобразование не будет выполнено, так как компилятор пытается сопоставить точный типы.
Это легко исправить, хотя:
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
с которые можно конвертировать в T
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);
// ^^^^
Других решений пока нет …