Частичная специализация или создание шаблона класса метода - PullRequest
7 голосов
/ 16 апреля 2019

У меня есть структура шаблона с несколькими параметрами шаблона

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

Эта структура отлично работает для всех шаблонов, кроме случая, когда Result void.Я понимаю, что Result{} не может быть реализован для типа void, поэтому мое текущее решение состоит в том, чтобы использовать частичную специализацию, подобную этой:

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

Это позволяет делать следующее:

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

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

Есть ли способ заставить mycl1.foo() компилироваться без частичной специализации класса в стандарте C ++ 14?Я мог бы использовать if constexr и комбинацию типа trait is_void_v, но я хочу найти, если есть способ:

  • специализация метода класса шаблона, частичное явное

  • создание экземпляра метода класса шаблона

1 Ответ

8 голосов
/ 16 апреля 2019

Хотя вы не можете сделать

Result foo()
{
    return Result{};
}

Если Result равно void, вы можете использовать

Result foo()
{
    return Result();
}

Поведение в этом случае такое же, и вы получитеВозвращено значение инициализированного объекта.Этот синтаксис допускается, когда Result равен void [expr.type.conv] \ 2

Если инициализатор представляет собой одиночное выражение в скобках, выражение преобразования типаэквивалентен (в определенности и если определен в значении) соответствующему приведенному выражению.Если тип имеет тип cv void, а инициализатор - (), выражение является значением указанного типа, которое не выполняет инициализацию.В противном случае выражение является prvalue указанного типа, чей результирующий объект инициализируется напрямую с помощью инициализатора.Для выражения вида T () T не должен быть типом массива.

Скоро появится, хотя вы сможете использовать

return Result{};

, даже если Resultvoid, поскольку C ++ 20 добавил в этот раздел, что {} будет работать также для void. [expr.type.conv] \ 2 теперь заявляет

Если инициализатор является одиночным выражением в скобках, выражение преобразования типа эквивалентно соответствующему выражению приведения.В противном случае, если тип имеет тип cv void, а инициализатор - () или {} (после расширения пакета, если оно есть), выражение является значением указанного типа, которое не выполняет инициализацию.В противном случае выражение является prvalue указанного типа, чей результирующий объект инициализируется напрямую с помощью инициализатора.Если инициализатор является необязательным списком выражений в скобках, указанный тип не должен быть типом массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...