依赖于模板的模板朋友 class
Dependency in template friend of template class
通过阅读标准试图找出这种语法的几个小时后,我放弃了尝试理解它。
我有一个模板 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>*);
我怎样才能将此 function/struct 加为好友?
[编辑:
以下适用于我机器上的 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 错误,但我必须承认我不是真的很确定。
不过,如果是这样的话,您会发现它很有用:
Class template with template class friend, what's really going on here?
Template friend
但是,我不太喜欢那个设计,你确定你真的需要构造函数的部分特化吗?你不能用 SFINAE 丢弃它们,或者访问一些具有特征 class 的子类型(或者你想要部分特化的任何其他东西,可以用其他东西代替)?
例如这些结构之一:
#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;
}
在我的机器上显示:
construction with a vector
construction with a list of NSt3__16vectorIiNS_9allocatorIiEEEE
construction with an iterator (supposedly) whose value_type isc
(当然我不知道你到底想做什么,所以我不确定,我会对此发表评论而不是将其放在答案中,但我没有足够的声誉为此,今天创建帐户)
通过阅读标准试图找出这种语法的几个小时后,我放弃了尝试理解它。 我有一个模板 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>*);
我怎样才能将此 function/struct 加为好友?
[编辑: 以下适用于我机器上的 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 错误,但我必须承认我不是真的很确定。
不过,如果是这样的话,您会发现它很有用:
Class template with template class friend, what's really going on here?
Template friend
但是,我不太喜欢那个设计,你确定你真的需要构造函数的部分特化吗?你不能用 SFINAE 丢弃它们,或者访问一些具有特征 class 的子类型(或者你想要部分特化的任何其他东西,可以用其他东西代替)?
例如这些结构之一:
#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;
}
在我的机器上显示:
construction with a vector
construction with a list of NSt3__16vectorIiNS_9allocatorIiEEEE
construction with an iterator (supposedly) whose value_type isc
(当然我不知道你到底想做什么,所以我不确定,我会对此发表评论而不是将其放在答案中,但我没有足够的声誉为此,今天创建帐户)