Demaunt
Demaunt

Reputation: 1243

Partial specialization or instantiation of template class method

I have template struct with several template parameters

template<class Result, class T, class K>
struct MyClass
{
public:
    Result foo()
    {
        return Result{};
    }
};

This struct works fine for all templates except the case when Result is void. I understand, that Result{} cannot be implemented to void type, so my current solution is to use partial specialization like this:

template<class T, class K>
struct MyClass<void, T, K>
{
public:
    void foo()
    {
        return;
    }
};

This allows to do following:

int main()
{
    MyClass<void, double, char> mycl1;
    MyClass<int, double, char> mycl2;

    mycl1.foo();
    mycl2.foo();
}

Is there a way to make mycl1.foo() compile without partial class specialization in C++ 14 standart? I could use if constexr and type trait is_void_v combination, but I want to find if there is a way to:

Upvotes: 7

Views: 487

Answers (1)

NathanOliver
NathanOliver

Reputation: 180710

While you cannot do

Result foo()
{
    return Result{};
}

If Result is void, you can use

Result foo()
{
    return Result();
}

The behavior in this case is the same and you will get a value initialized object returned. This syntax is allowed when Result is void by [expr.type.conv]\2

If the initializer is a parenthesized single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression. If the type is cv void and the initializer is (), the expression is a prvalue of the specified type that performs no initialization. Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized with the initializer. For an expression of the form T(), T shall not be an array type.

Coming soon though you will be able to use

return Result{};

even if Result is void as C++20 added to that section that {} will work as well for void. [expr.type.conv]\2 now states

If the initializer is a parenthesized single expression, the type conversion expression is equivalent to the corresponding cast expression. Otherwise, if the type is cv void and the initializer is () or {} (after pack expansion, if any), the expression is a prvalue of the specified type that performs no initialization. Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized with the initializer. If the initializer is a parenthesized optional expression-list, the specified type shall not be an array type.

Upvotes: 8

Related Questions