Есть ли ошибка компилятора, представленная моей реализацией свойства 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, и является ли эта конкретная конструкция правильной.
Ответы
Ответ 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 реализует резолюцию.