当foo是一个接受单个模板参数的结构时,foo <type1,types ... =“”>合法吗?

时间:2019-01-22 05:38:04

标签: c++ templates clang libstdc++ compiler-bug

使用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)。

Here是一个用例:

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 so gcc can pass compile。这是c的错误吗?

1 个答案:

答案 0 :(得分:3)

如果我正确地解释了[temp.variadic]/7,就好像是Clang错误:

  

当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>等效。

当然,如果包不是为空,那么我们将传递过多的参数,这些参数 格式错误。但是事实并非如此。