`foo <Type1, Types ...>` допустимо, когда foo является структурой, которая принимает один параметр шаблона? - PullRequest
0 голосов
/ 22 января 2019

При игре с libstdcxx test_property:

template<template<typename...> class Property,
       typename Type1, typename... Types>
constexpr bool
test_property(typename Property<Type1, Types...>::value_type value)
{
    return (Property<Type1, Types...>::value == value
      && Property<Type1, Types...>::type::value == value);
 }

class Property принимает как минимум 1 параметр шаблона (Type1).

Здесь - это пример использования:

static_assert(test_property<is_copy_assignable, ExceptMoveAssignClass>(false), "");

Но я обнаружил, что clang не работает нормально с этой функцией:

prog.cc:29:3: error: no matching function for call to 'test_property'
                test_property<std::is_copy_assignable, DeletedMoveAssignClass>(false);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:12:1: note: candidate template ignored: substitution failure [with Property = std::is_copy_assignable, Type1 = DeletedMoveAssignClass]: too many template arguments for class template 'is_copy_assignable'
test_property(typename Property<Type1, Types...>::value_type value)
^                      ~~~~~~~~
1 error generated.

Основная причина в том, что clang не позволяет class Property быть классом, который принимает только один параметр шаблона, такой как template< class T > struct is_copy_assignable;.Как только class Property будет изменен на Property<Type1>, он будет успешно скомпилирован:

template<template<typename...> class Property, typename Type1>
constexpr bool
ya_test_property(typename Property<Type1>::value_type value)
{
    return (Property<Type1>::value == value
        && Property<Type1>::type::value == value);
}

здесь это демо https://wandbox.org/permlink/LlL1o57Yted5WZo5

Конечно, эта функция из libstdcxx, , поэтомуGCC может передать компиляцию .Ошибка этого лягушки?

1 Ответ

0 голосов
/ 22 января 2019

Похоже на ошибку Clang, если я правильно интерпретирую [temp.variadic] / 7 :

Когда N равно нулю, создание экземпляра расширения приводит к пустомусписок.Такое создание не изменяет синтаксическую интерпретацию включающей конструкции, даже в тех случаях, когда полное исключение списка в противном случае было бы неправильным или привело бы к неоднозначности в грамматике.[ Пример :

template<class... T> struct X : T... { };
template<class... T> void f(T... values) {
  X<T...> x(values...);
}

template void f<>();    // OK: X<> has no base classes
                        // x is a variable of type X<> that is value-initialized

- конец примера]

Точно так же, пока std::is_copy_assignable<ExceptMoveAssignClass , > не сформирован, пустая пачка не должна помещать нас вэто состояние.Он должен быть эквивалентен std::is_copy_assignable<ExceptMoveAssignClass>, который правильно сформирован.

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

...