以下内容无法编译,该怎么办?我认为该示例显示了我的意图,但是如果人们感到困惑,我将尝试添加一些内容。

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

10-05 20:47
查看更多