Подтвердить что ты не робот

Неожиданное поведение с псевдонимом типа шаблона в VS2015

Следующий код компилируется с сообществом VS15 и выводит "Hello".

#include <functional>
#include <iostream>

template<typename T>
using void_template_alias_t = void;

template<typename T>
using Func = std::function<void( T )>;

template<typename T>
using FuncVoid = Func<void_template_alias_t<T>>;

int main()
{
    FuncVoid<void> hello = [] { std::cout << "Hello\n"; };
    hello();
}

Я думаю, что это не разрешено компилировать.

Я играл, код был немного сложнее. Я наивно ожидал, что это сработает, но вдруг понял, что этот код не должен компилироваться, потому что вы не можете сделать Func<void> (или я ошибаюсь в этом?).

  • Я нашел волшебное обходное решение?
  • Это новое поведение из стандарта С++ 14?
  • Или это просто ошибка компилятора?

Изменить: Следующая упрощенная версия не компилируется.

#include <functional>
#include <iostream>

template<typename T>
using Func = std::function<void( T )>;

int main()
{
    Func<void> hello = [] { std::cout << "Hello\n"; };
    hello();
}
  • Так почему же код выше компилируется и работает, как я и ожидал?
  • Это правильная реализация, если нет, как бы она выглядела?
4b9b3361

Ответ 1

Или это просто ошибка компилятора?

Это. Как упоминалось в @T.C., CWG # 577 имеет значение:

[...] там была выражена обеспокоенность по поводу обработки шаблонов функций и функции-члены шаблонов классов, если было изменено правило С++: для параметра шаблона T, будет функция, принимающая один параметр типа T становятся непараметрической функцией, если она была создана с помощью T = void

Это обоснованная жалоба, но, к сожалению, для вас, функции-члены/функции-члены-функции и идентификаторы типов были одинаково затронуты разрешением:

Список параметров, состоящий из одного неназванного параметра не зависящего типа void, эквивалентен списку пустых параметров.

таким образом оба ваши фрагменты плохо сформированы, поскольку тип параметра действительно зависит.


Является ли это правильной реализацией, если нет, как бы она выглядела?

Нет правильной реализации. Если вам нужен тип функции с пустым списком параметров, вам нужно указать, что независимо от параметров шаблона.

Так почему же код выше компилируется и работает, как я и ожидал?

Мое лучшее предположение: VС++ выполняет замену void_template_alias_t<T> после того, как убедиться, что тип параметра не является зависимым типом "cv void", но перед тем, как преобразовать "void → empty list". Однако часто трудно понять, как VС++ (или любой компилятор, если на то пошло) думает внутренне.