为模板参数提供帮助

时间:2011-02-03 20:27:16

标签: c++ templates friend

不可能与模板参数相关,因为标准不允许它。那我怎么能有效地做同样的事呢?

我想要的基本上是一种在拥有它的对象之外无法使用的类型。为什么不是重点,但如果你真的必须知道,我正在尝试制定一套智能指针来解决共享自有资源的问题。因此,我想要做的就是这样,如果它有效:

template < typename T, typename Owner >
struct accessible_member
{
private:
  accessible_member() : val(T()) {}
  accessible_member(T const& t) : val(t) {}

  operator T& () { return val; }
  operator T const& () const { return val; }

  member_ptr<T> operator & () { return member_ptr<T>(val); }

  friend class Owner;
};

因此,一个类不能将这个对象保存为成员,除非它声明自己是所有者,如果它足够愚蠢地暴露它,那么就不可能在类之外使用这么愚蠢。

6 个答案:

答案 0 :(得分:5)

你对C ++ 98/03是正确的。但是,C ++ 0x(n3225 11.4 / 3)允许您使用以下语法执行此操作:

friend Owner;

看看你的编译器是否允许你这样做。尝试启用C ++ 0x支持。否则解决方法更加丑陋:

struct Owner
{
    typedef Owner self;
};

...

然后根据您的编译器之一:

friend typename Owner::self;

或:

friend class Owner::self;

答案 1 :(得分:3)

您可以使用此功能,然后让所有拥有者继承自所有者

然后,您可以使用所有者类私下包装 accessible_member 中使用的方法。
所有者现在可以访问 accessible_member 。朋友不是继承的,所以你可以提供(包装)必要的方法,这样所有继承所有者的类都可以使用 accessible_member

这是一个2级解决方案,但它保持了封装级别。

template < typename U >
struct Owner 
{
   protected:
   accessible_member<U> newAccessible_member() { return accessible_member<U>(); }
   accessible_member<U> newAccessible_member(U const& u) { return accessible_member<U>(u); }
   .....

};

template < typename T >
struct accessible_member
{
private:
  accessible_member() : val(T()) {}
  accessible_member(T const& t) : val(t) {}

  operator T& () { return val; }
  operator T const& () const { return val; }

  member_ptr<T> operator & () { return member_ptr<T>(val); }


  template < typename U> friend class Owner;
};

然后,您可以使用受保护的方法间接使用来自Owner的结构中的accessible_member:

struct Blah: Owner<int>
{
   void Dosomething() {
       accessible_member<int> blah= newAccessible_member();
   }
};

查看Template Friends上的最后一个示例。

答案 2 :(得分:1)

7.1.5.3 p2说:

  

[注意:这意味着,在一个   带有模板的类模板   type-parameter T,声明   朋友班T;是不正确的。]

因此,任何允许您使用它的任何解决方案都将符合非标准。

答案 3 :(得分:0)

如何简单地定义一个简单地从accessible_member继承的私有嵌套类型?像

这样的东西
class Owner
{
    template < typename T >
    class accessible_member : public ::accessible_member< T > {};
};

当然,这仍然意味着任何人都可以使用原始的accessible_member类型,因此可能没有太多用处。

答案 4 :(得分:0)

我能看到的唯一解决方法是相当难看并使用CRTP:

template <typename T>
struct CanUseAccessibleMember
{
    template <typename T>
    static const T& get(const accessible_member<T>& m)
    { return static_cast<const T&>(m); }

    // Etc. You can even specialize this class.
};

struct ExampleOwner 
    : protected CanUseAccessibleMember<ExampleOwner>
{
    // Do whatever you want with accessible members here
    // but you have to use the get syntax
};

template <typename T, typename Owner>
class accessible_member
{
    // Implement members as you did

    friend struct CanUseAccessibleMember<Owner>;
};

答案 5 :(得分:0)

就我所见,在C ++ 98下,这将有所改变。它使用g++-4.1 -Wall -Wextra -pedantic -ansi -std=c++98

编译时没有任何警告

只需更改

friend Owner;

struct Wrapper { typedef Owner type; };
friend class Wrapper :: type;

(我在Stackoverflow上得到了答案,这个问题出现了几次:Template parameter as a friend