晚期默认模板参数声明的 clang++ 错误

clang++ error on late default template parameter declaration

以下代码可以用 g++ 编译,但不能用 clang++ (3.6) 编译:

// Forward declaration:
template <class S, class T>
struct Base;

template <class T>
struct BaseFriend {
    friend struct Base<int, T>;
};

// Actual declaration:
template <class S, class T = int>
struct Base {
    void foo() {}
};

struct DerivedFriend : BaseFriend<int> {};

struct Derived : Base<int> {
    void foo(int) {
        Base<int>::foo();
    }
};

Derived::foo定义中出现错误:

error: too few template arguments for class template 'Base'
    Base<int>::foo();
    ^
test.cpp:3:8: note: template is declared here
struct Base;
       ^

经过一些小的修复后错误消失,例如:

  1. 如果默认模板参数是在前向声明而不是实际声明中定义的。
  2. 或者不使用DerivedFriend

但是,原始代码有什么问题?

绝对是 clang 错误,看起来像 #10147。该标准明确允许 [temp.param]/10:

The set of default template-arguments available for use with a template declaration or definition is obtained by merging the default arguments from the definition (if in scope) and all declarations in scope in the same way default function arguments are (8.3.6). [ Example:

template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;

is equivalent to

template<class T1 = int, class T2 = int> class A;

—end example ]