以下内容无法编译,该怎么办?我认为该示例显示了我的意图,但是如果人们感到困惑,我将尝试添加一些内容。
template<typename T>
class A
{
private:
struct B
{
template<typename T2>
B& operator=( const A<T2>::B& right ){} // how can I make this work?
};
template<typename T2> friend class A;
template<typename T2> friend class A<T2>::B;
};
最佳答案
赋值运算符的基本思想是有缺陷的,因为即使添加了typename
,这也是不可推论的上下文。这样,除非您明确指定类似B.operator=<some_type>(other_B)
的类型,否则将不会推断出模板参数,并且赋值运算符也将永远无法工作。
一个更简单的版本是使其成为常规功能模板,而SFINAE就是您的出路。
#include <type_traits>
template<class> struct is_a_B;
template<class B2>
typename std::enable_if<
is_a_B<B2>::value,
B&
>::type operator=(B2 const& other){
// ...
}
现在剩下的就是
is_a_B
类型特征。您可以通过可能的误报使自己变得容易:template<class B>
struct is_a_B{
typedef char yes;
typedef yes (&no)[2];
template<class T>
static yes test(typename T::I_am_a_B_type*);
template<class T>
static no test(...);
static bool const value = sizeof(test<B>(0)) == sizeof(yes);
};
只需在
I_am_a_B_type
类中提供B
typedef。Live example on Ideone。注释掉
b1 = 5;
行,并编译为seen here。现在,使用稍微有些变态的复杂方法,而不会出现假阳性。 :)
template<bool Cond, class OnTrue>
struct and_v{
static bool const value = OnTrue::value;
};
template<class OnTrue>
struct and_v<false, OnTrue>{
static bool const value = false;
};
template<class B>
struct is_a_B{
typedef char yes;
typedef yes (&no)[2];
template<class T>
static yes has_parent(typename T::parent*);
template<class T>
static no has_parent(...);
template<class T>
static yes is_A(A<T>*);
static no is_A(...);
template<class T>
struct lazy_test{
typedef typename std::add_pointer<typename T::parent>::type p_type;
static bool const value = sizeof(is_A(p_type(0))) == sizeof(yes);
};
static bool const value = and_v<sizeof(has_parent<B>(0)) == sizeof(yes),
lazy_test<B>>::value;
};
为此,您需要在
typedef A<T> parent;
内添加一个B
。它分为两个部分:首先,我测试
parent
typedef是否存在,是否存在如果它实际上是
A
类模板的typedef。可悲的是,逻辑运算符(
&&
,||
,?:
)不会像我希望的那样在模板代码中短路,因此我不得不编写那些and_v
模板+一个懒惰的测试器,只有在parent
typedef存在。Live example on Ideone。再次,注释掉
b1 = 5;
行以使其编译为seen here。