【问题标题】:Dependency in template friend of template class模板类的模板友元中的依赖
【发布时间】:2015-10-21 03:32:01
【问题描述】:

经过数小时试图通过阅读标准来找出这种语法后,我放弃了试图理解这一点。 我有一个带有模板构造函数的模板类,我需要部分专门化,因为这是不可能的,我将构造函数实现包装在不同的模板中:

template<class T> 
struct A; //forward declaration
namespace impl {
template<class T>
struct wrap {
    template<class U>
    struct AConstructor {
        static void construct(A<T>*thisPtr) {...}
    };
    //some partial specialization...
};
template<class T>
struct dummy{};
} //end of namespace
template<class T>
struct A {
   template<class U>
    A(dummy<U>) {
        impl::template wrap<T>::template AConstructor<U>::construct(this);
    }
};

这本来可以正常工作,但我需要在构造函数实现中访问 A&lt;T&gt; 的私有成员,所以我需要一个朋友声明,这就是它变得棘手的地方。 我尝试在可能的位置使用或不使用template 关键字,并得到编译错误是Visual Studio:第一个错误C2992(无效或缺少模板参数列表)和其他错误C2952(模板声明缺少模板参数列表):

template<class T>
class A {
    //1
    template<class U>
    friend struct impl::template wrap<T>::template AConstructor;
    //2,3 I also tried removing the static identifier with this declaration
    template<class U>
    friend void impl::template wrap<T>::template AConstructor<U>::construct(A<T>*);

我怎样才能成为这个函数/结构的朋友?

【问题讨论】:

  • 试试这个看看它是否有效? : template 朋友 void impl:: wrap:: AConstructor::construct(A*);

标签: c++ templates friend


【解决方案1】:

[编辑: 以下适用于我的机器上的 g++ 4.9.0 和 clang 3.5:

template<class T>
struct dummy {};

template<class T>
struct A {
private:
  template<class U>
  struct AConstructor {
    static void construct(A<T>* thisPtr) {
      thisPtr->foo = 42;
    }
  };

  template<class>
  friend class AConstructor;

public:
  template<class U>
  A(dummy<U>) {
    AConstructor<U>::construct(this);
  }

  void print() const {
    std::cout << foo << std::endl;
  }

private:
  int foo;
};

int main() {
  A<void> foobar( (impl::dummy<void>()) );
  foobar.print();
  return 0;
}

]

对我来说,这是:

template<class T> 
struct A; //forward declaration

namespace impl {

  template<class T>
  struct wrap {
    template<class U>
    struct AConstructor {
      static void construct(A<T>* thisPtr) {
        thisPtr->foo = 42;
      }
    };
    //some partial specialization...
  };

  template<class T>
  struct dummy{};

} //end of namespace

template<class T>
struct A {
  template<class>
  friend class impl::wrap<T>::AConstructor;

  template<class U>
  A(impl::dummy<U>) {
    impl::template wrap<T>::template AConstructor<U>::construct(this);
  }

  void print() const {
    std::cout << foo << std::endl;
  }

private:
  int foo;
};

int main() {
  A<void> foobar( (impl::dummy<void>()) );
  foobar.print();
  return 0;
}

使用 g++ 4.9.0 编译并按预期工作(它在标准输出上显示 42)虽然编译失败并使用 clang 3.5,我想说这是一个 clang 错误,但我必须承认我不太确定那个。 不过,如果是这种情况,您会发现这很有用:
Class template with template class friend, what's really going on here?
Template friend

但是,我不太喜欢这种设计,你确定你真的需要构造函数的部分专业化吗?您不能使用 SFINAE 丢弃它们,或者使用 trait 类访问某些子类型(或任何其他您想要部分专业化的东西,可以用其他东西代替)?
例如以下结构之一:

#include <list>
#include <vector>

template<class T> 
struct is_vector : std::false_type {};

template<class T>
struct is_vector<std::vector<T>> : std::true_type {};

struct A {
  template<
    class T, typename std::enable_if<is_vector<T>::value, void*>::type = nullptr
  >
  A(T) {
    std::cout << "construction with a vector" << std::endl;
  }

  template<class T>
  A(std::list<T>) {
    std::cout << "construction with a list of " << typeid(T).name();
    std::cout << std::endl;
  }

  template<
    class T,
    typename std::enable_if<!is_vector<T>::value, void**>::type = nullptr
  >
  A(T) {
    std::cout << "construction with an iterator (supposedly) whose value_type "
                 "is";
    std::cout << typeid(typename std::iterator_traits<T>::value_type).name();
    std::cout << std::endl;
  }
};

int main() {
  A(std::vector<int>());
  A(std::list<std::vector<int>>());
  A((char*) nullptr);
  return 0;
}

在我的机器上显示这个:

用向量构造
使用 NSt3__16vectorIiNS_9allocatorIiEEEE 列表构造
使用其 value_type 为 c 的迭代器(假设)构造

(当然我不知道你想做什么,所以我不确定,我会对此发表评论而不是将其放在答案中,但我没有足够的声誉去做所以,今天创建了帐户)

【讨论】:

  • 实际上,我想到的是带有类型特征的设计,问题是我使用的是 gcc 4.1,所以我不能使用大多数类型特征(有些是我自己实现的)。这个特化是检查一些继承,所以我不能自己实现它,所以我求助于部分特化。
猜你喜欢
  • 1970-01-01
  • 2010-12-19
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 2013-09-18
  • 2018-09-07
  • 2011-04-19
相关资源
最近更新 更多