alfC
alfC

Reputation: 16242

Idiom for default initialization depending on type

I have a template class that takes default member values.

template<class T = std::string>
struct A{
    T val = {"val"};
};

However sometimes the default values do not make sense, for example:

A<int> a1;  // cannot initialize int from "val"

Is there is good idiom to handle this issue?

I came up with this solution, which is quite verbose.

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");
};

(The other option is to set up a Boost.Fusion map to have a default value per type, but it is even more code and all the cases need to be handled.)


Update (thanks @Someprogrammerdude): Another alternative for very specific cases (no valid based on syntax) can be done by specializing the constructor:

template<class T = std::string>
struct A{
    T val;// = valid_or_default<T>("val");
    A() : val{}{}
};

template<> A<std::string>::A() : val{"val"}{}

Upvotes: 1

Views: 52

Answers (3)

bolov
bolov

Reputation: 75688

Here is a C++17 solution:

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

Upvotes: 2

R Sahu
R Sahu

Reputation: 206567

Here's another option.

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

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409166

I still don't know what the original problem you try to solve is, or why you need to use a compile-time fixed-value for the initialization, but as it seems your structure is an aggregate you could simply use aggregate initialization:

template<typename T = std::string>
struct A
{
    T val;
};

// ...

A a = { "val" };
A<int> b = { 1 };

Upvotes: 2

Related Questions