来自不同命名空间的模板模板参数可以成为朋友吗?

Jan*_*sek 5 c++ templates template-templates

如果这个问题的标题不太有用,我道歉; 我不知道在不给出以下示例的情况下提出这个问题的简洁方法:

template <template <class> class Arg>
class C {
    typedef C<Arg> type;
    friend class Arg<type>;
  public:
    C() {
        a_.set(this);
    }
  private:
    int i_;
    Arg<type> a_;
};

template <class Type>
class Arg1 {
  public:
    void set(Type* t) {
        t_ = t;
        t_->i_ = 1;
    }
  private:
    Type* t_;
};

namespace NS {

    template <class Type>
    class Arg2 {
      public:
        void set(Type* t) {
            t_ = t;
            t_->i_ = 2;
        }
      private:
        Type* t_;
    };

}
Run Code Online (Sandbox Code Playgroud)

如你所见,Arg2是一份副本Arg1.但是,VS 2008仅允许Arg1用作模板参数:

int main() {
    C<Arg1> c1; // compiles ok
    C<NS::Arg2> c2; // error C2248

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误是'C<Arg>::i_' : cannot access private member declared in class 'C<Arg>'.如果i_公开的话,一切都很好,所以这似乎是一个友谊问题.

当模板模板参数位于不同的命名空间中时,导致友谊声明失败的原因是什么?

Pot*_*ter 0

命名空间成员资格不会影响友谊资格。这是一个编译器错误。

friend不过, 和namespace是相互作用的语言功能,因此错误的出现并不特别令人惊讶。也许它实际上是在封闭的命名空间中添加一个无意义的前向声明,::Arg2<type>.