5

只有在某些(编译时)条件为真时,我才想声明一个朋友类。例如:

// pseudo-C++
class Foo {
    if(some_compile_time_condition) {
        friend class Bar;
    }
};

我在互联网上没有找到任何解决方案。我浏览了在编译时动态生成结构问题的所有答案。他们中的许多人使用 C++11 std::conditional,但我想知道是否可以在不使用预处理器的情况下在 C++03 中执行此操作。

此解决方案https://stackoverflow.com/a/11376710/252576将不起作用,因为friend船舶未继承(具有继承的朋友类)。

编辑只是为了使它更容易看到,如下评论中所述:此要求是不寻常的。这是我正在从事的硬件仿真新研究项目的一部分。测试台是用 C++ 编写的,我想以波形显示变量。我研究了各种其他选项,并发现出于实际考虑我需要使用 a friend class。朋友将捕获值并生成波形,但我希望仅在需要波形时才让朋友,而不是一直。

4

5 回答 5

6

使用friend std::conditional<C, friendclass, void>::type;whereC是你的条件。非类类型的朋友将被忽略。

条件模板在 C++03 中很容易实现。但是,由于 C++03 不支持 typedef 朋友,因此您需要在此处使用以下语法

namespace detail { class friendclass {}; }

class Foo {
  friend class std::conditional<C, 
    friendclass, detail::friendclass>::type::friendclass;
};

请注意,详细虚拟类名称需要与此解决方法中潜在朋友的名称相匹配。

于 2012-12-21T08:51:46.420 回答
2

[class.friend]/3 告诉这个:

未声明函数的友元声明应具有以下形式之一:
友元详述类型说明符;
朋友简单类型说明符;
朋友类型名说明符;

因此,没有宏就不可能有条件地声明一个类的朋友。

于 2012-12-21T07:03:23.667 回答
2

不幸的是,这似乎在 C++ 编译器中是不可能的:也就是说,似乎只有预处理器可以在这里提供帮助。注意:Johannes 有提议,所以有希望!

但是我会注意到:

  • 友谊不需要你实际使用它
  • 友谊是纯编译时构造(如访问说明符),不会对任何主要编译器产生任何运行时损失

没有理由不拥有无条件的友谊,而只有在满足某些条件(静态或动态)时才使用它。

注意:将来,这是 static_if 提案可以涵盖的内容。

于 2012-12-21T07:35:52.780 回答
0

注意: Johannes已经非常成功了。在 '03 中,你不能与 typedef 成为朋友——但如果你知道你有一个类,那么你可以参考它的injected class name.

Johannes 的回答还具有使用标准库功能的好处,这也总是一件好事。

#define some_compile_time_condition 0

class Foo;

template <int Condition> class  TestCondition {
private:
  friend class Foo;
  struct Type {
    struct Bar;
  };
};

template <> class TestCondition<1> {
public:
  typedef Bar Type;
};

struct Bar
{
public:
  void foo (Foo &);
};

class Foo {
private:
  friend struct TestCondition< some_compile_time_condition >::Type::Bar;
  int m_i;
};

void Bar::foo (Foo & foo)
{
  foo.m_i = 0;
}

它仍然与始终有一个朋友的要求不同Foo,但结识的阶级会根据选项的值而变化。

Foo一个有趣的附带问题是,将带和不带的版本都some_compile_time_condition 设置为 1是否违反 ODR 。

于 2012-12-21T08:54:00.087 回答
0

我认为您需要 1 个预处理器并在其中编写源代码。

bool flag = false;
#ifdef _MY_FRIEND_
    friend class sample
    flag = true;
#endif

if (flag)
{
 ...
 ...
 ...
}

class Foo {
#ifdef _MY_FRIEND_
    friend class Bar;
#endif
}

};

这里 _MY_FRIEND_ 是一个预处理器,如果您添加该预处理器,那么在编译时您的类 Bar 将成为朋友类...当您需要类 Bar 作为朋友类时,您可以在任何地方使用该预处理器。其他明智的编译没有预处理器然后它不会允许你将 Bar 添加为 Foo 的朋友类

如果我理解错误的问题,请纠正我。

于 2012-12-21T12:11:28.233 回答