依赖于模板类的模板友元
Dependency in template friend of template class
我花了几个小时试图通过阅读标准来找出这种语法,我放弃了理解它的尝试。我有一个模板类,其中有一个模板构造函数,我需要部分特化,因为这是不可能的,所以我将构造函数实现包装在另一个模板中:
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<T>
的私有成员,所以我需要一个友元声明,这就是它变得棘手的地方。我在可能的位置尝试或不使用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>*);
如何添加这个函数/结构体的好友?
[编辑:下面的代码可以在我的机器上同时使用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下可以编译并按预期工作(它在stdout上显示42),尽管在clang 3.5下编译失败,我想说这是clang的错误,但我必须承认我不是很确定。不过,如果是这样的话,你会发现它很有用:
类模板和模板类友,这里到底发生了什么?
模板的朋友
然而,我真的不喜欢这样的设计,你确定你真的需要构造函数的部分专门化吗?你不能用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_9allocatororiieeee的列表
的迭代器构造(假设)
使用value_type为isc
(当然我不知道你到底想做什么,所以我不确定,我会评论这个,而不是把它放在一个答案,但我没有足够的声誉这样做,今天创建的帐户)
相关文章:
- C++模板来检查友元函数的存在
- 模板类无法识别友元运算符
- 如何使用单独文件中的派生类访问友元函数对象
- 模板化的类和友元函数
- 为什么创建友元类的实例会导致"undefined reference to"错误?
- 如何在嵌套类中正确使用友元声明?
- 友元函数无法访问私有数据成员 (c++)
- 继承和友元函数,从基类访问受保护的成员
- 将子类方法声明为基类的友元
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 为什么内存屏障依赖于变量?
- 反转依赖于 end() 的迭代器
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- 在将函数声明为友元时,尖括号的含义是什么?
- Scott Meyers关于首选非成员非友元方法的建议是否适用于对象构造?
- 使用友元类减少编译时间和依赖关系
- C++:特定于友元的对象(嵌套类)
- 对依赖于参数的查找和友元函数定义的混淆
- 依赖于模板类的模板友元
- 如何解决c++中友元声明的循环依赖