与模板参数建立好友关系

发布于 2024-10-15 11:10:36 字数 618 浏览 4 评论 0原文

不可能将模板参数添加为好友,因为标准不允许这样做。那么我怎样才能有效地得到同样的东西呢?

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

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;
};

因此,一个类不能将这个对象作为成员持有,除非它声明自己是所有者,并且如果它足够愚蠢地按原样公开它,那么它将是不可能在课堂外使用,因为太愚蠢了。

It's impossible to friend a template parameter because the standard disallows it. How might I get effectively the same thing then?

What I want is basically a type that is unusable outside the object which owns it. Why is rather beside the point but if you really must know, I'm trying to formulate a set of smart pointers that answer the problem of sharing an owned resource. Thus what I'm looking to do is something like so, if it worked:

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;
};

Thus a class can't hold this object as a member unless it declares itself the owner, and if it's silly enough to expose it as is, it will be impossible to use outside the class being so stupid.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

悟红尘 2024-10-22 11:10:36

您对 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;

You are correct about C++98/03. However C++0x (n3225 11.4/3) allows you to do this with this syntax:

friend Owner;

See if your compiler will let you do that. Try turning on C++0x support. Otherwise the workarounds are uglier:

struct Owner
{
    typedef Owner self;
};

...

Then depending on your compiler one of:

friend typename Owner::self;

or:

friend class Owner::self;
怪我太投入 2024-10-22 11:10:36

您可以使用它,然后让所有所有者继承 Owner

然后,您可以使用 Owner 类来私有包装 accessible_member 中使用的方法。
所有者现在可以访问accessible_member。 Friend 不是继承的,因此您可以提供(包装)必要的方法,以便所有继承 Owner 的类都可以使用 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();
   }
};

查看最后一个示例 模板好友

You could use this, and then let all the owners inherit from Owner.

You could then use Owner class to wrap privately the methods used in accessible_member.
accessible_member is now accessible to Owner. Friend is not inherited, so you can supply (wrap) the necessary methods so all the classes that inherit Owner can use accessible_member.

It's a 2 level solution but it keeps the level of encapsulation.

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;
};

Then you can use the accessible_member indirectly in structs that inherit from Owner using the protected methods:

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

Look at the last example at Template Friends.

徒留西风 2024-10-22 11:10:36

7.1.5.3 p2 说:

[注意:这意味着,在一个
带有模板的类模板
类型参数 T,声明
朋友等级T;格式不正确。]

因此,任何允许您以任何方式实现的解决方案都将不符合标准。

7.1.5.3 p2 says:

[Note: this implies that, within a
class template with a template
type-parameter T, the declaration
friend class T; is ill-formed.]

As a result, any solution that allows you to it by any mean will be non standard conformant.

待天淡蓝洁白时 2024-10-22 11:10:36

简单地定义一个从accessible_member继承的私有嵌套类型怎么样?当然

class Owner
{
    template < typename T >
    class accessible_member : public ::accessible_member< T > {};
};

,这仍然意味着原始 accessible_member 类型可供任何人使用,因此考虑起来可能没有多大用处。

What about simply defining a private nested type that trivially inherits from accessible_member? Something like

class Owner
{
    template < typename T >
    class accessible_member : public ::accessible_member< T > {};
};

Of course that still means the original accessible_member type is available to anyone so it's maybe not of much use come to think of it.

街角迷惘 2024-10-22 11:10:36

我能看到的唯一解决方法相当丑陋,并且使用 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>;
};

The only workaround I can see is rather ugly and uses the 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>;
};
左耳近心 2024-10-22 11:10:36

据我所知,在 C++98 下只要稍加改变就可以了。它编译时没有对我发出任何警告 g++-4.1 -Wall -Wextra -pedantic -ansi -std=c++98

只需更改

friend Owner;

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

(我在 Stackoverflow 上得到了答案,这个问题已经出现了几次:模板参数作为朋友

That will work, with a little change, under C++98 as far as I can see. It compiled without any warnings for me with g++-4.1 -Wall -Wextra -pedantic -ansi -std=c++98

Just change

friend Owner;

to

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

(I got that answer on Stackoverflow, this question has come up a few times: Template parameter as a friend )

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文