我有一个采用默认成员值的模板类。
template<class T = std::string>
struct A{
T val = {"val"};
};
但是有时默认值没有意义,例如:
A<int> a1; // cannot initialize int from "val"
是否有处理这个问题的好习惯?
我想出了这个解决方案,这很冗长。
template<class T, class TT>
auto valid_or_default(TT&& other) ->
decltype(T{std::forward<TT>(other)}){return T{std::forward<TT>(other)};}
template<class T>
auto value_of_default(...){return T{};}
template<class T = std::string>
struct A{
T val = valid_or_default<T>("val");
};
(另一个选项是将Boost.Fusion映射设置为每种类型都有默认值,但是它甚至是更多的代码,需要处理所有情况。)
更新(感谢@Someprogrammerdude): 对于特殊情况(基于语法无效)的另一种选择可以通过专门构造函数来完成:
template<class T = std::string>
struct A{
T val;// = valid_or_default<T>("val");
A() : val{}{}
};
template<> A<std::string>::A() : val{"val"}{}
答案 0 :(得分:2)
我仍然不知道您尝试解决的原始问题是什么,或者为什么您需要使用编译时固定值进行初始化,但似乎您的结构是一个聚合您可以简单地使用aggregate initialization:
template<typename T = std::string>
struct A
{
T val;
};
// ...
A a = { "val" };
A<int> b = { 1 };
答案 1 :(得分:2)
这是C ++ 17解决方案:
template<class T, class TT>
auto valid_or_default(TT&& other)
{
if constexpr (std::is_constructible_v<T, TT>)
return T{std::forward<TT>(other)};
else
return T{};
}
答案 2 :(得分:1)
这是另一个选择。
template <typename T>
T get_default_value()
{
return {};
}
template <>
std::string get_default_value<std::string>()
{
return "val";
}
template<class T = std::string>
struct A {
T val = get_default_value<T>();
};