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

Есть ли ошибка компилятора, представленная моей реализацией свойства is_complete?

Я написал этот шаблон шаблона С++ 11, чтобы проверить, завершен ли тип:

template <typename...>
using void_t = void;

template <typename T, typename = void>
struct is_complete : std::false_type
{};

template <typename T>
struct is_complete<T, void_t<decltype(sizeof(T))>> : std::true_type
{};

и протестировал его следующим образом:

struct Complete {};

int main()
{
    std::cout << is_complete<Complete>::value
              << is_complete<class Incomplete>::value
              << '\n';
}

Я ожидал, что тестовая программа напечатает 10, и это результат, который я получаю, когда компилирую его с помощью clang 3.4. Однако при компиляции с gcc 4.9 вместо этого он печатает 11 - ошибочно идентифицируя class Incomplete как завершенную.

Я точно не знаю, правильно ли мой код, но мне кажется, что даже если это неправильно, оно должно вести себя одинаково для обоих компиляторов.

Вопрос 1: Правильно ли мой код?
Вопрос 2: Я нашел ошибку в одном из компиляторов?

ИЗМЕНИТЬ:

Я не прошу заменить мой код. Я спрашиваю, есть ли ошибка в gcc или clang, и является ли эта конкретная конструкция правильной.

4b9b3361

Ответ 1

Проблема, по-видимому, связана с определением void_t. Определяя его как

template<typename... Ts>
struct make_void { typedef void type;};

template<typename... Ts>
using void_t = typename make_void<Ts...>::type;

вместо этого дает правильный результат (10) для обоих компиляторов (Demo).

Я считаю, что это та же проблема, отмеченная в разделе 2.3 N3911, в документе, предлагающем void_t, и CWG-выпуск 1558. По сути, в стандарте неясно, могут ли неиспользуемые аргументы в специализациях шаблонов псевдонимов привести к сбою замены или просто игнорируются. Резолюция проблемы РГП, принятая на заседании Комитета в ноябре 2014 года, разъясняет, что более короткое определение void_t в вопросе должно работать, и GCC 5.0 реализует резолюцию.