用于类型初始化的默认成语

时间:2018-08-13 22:26:54

标签: c++11 default-value member-variables

我有一个采用默认成员值的模板类。

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"}{}

3 个答案:

答案 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>();
};