7
votes

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:

  • specialization of template class method partial explicit

  • instantiation of template class method

1
void main() is not valid, fixed that for you463035818_is_not_a_number
@user463035818 won't the compiler complain that you aren't returning anything from main?user10957435
@Chipster main is the one exception where the return is optional, if you dont write it the compiler will return 0; for you463035818_is_not_a_number
Using partial specialization of the class template seems to be a good strategy to me. Are you running into any problems while using it?R Sahu

1 Answers

8
votes

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.