Я хочу объявить класс друга только в том случае, если какое-либо условие (во время компиляции) выполняется. Например:
// 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
Корабль не передается по наследству ( класс друга с наследованием ).
редактировать Просто чтобы сделать это более заметным, как указано ниже в комментарии: Это требование необычно. Это часть нового исследовательского проекта по аппаратному моделированию, над которым я работаю. Testbench написан на C ++, и я хочу отобразить переменные в форме сигнала. Я исследовал различные другие варианты, и понял, что мне нужно использовать friend class
Из-за практических соображений. Друг захватит значения и сгенерирует сигнал, но я бы предпочел иметь друга только тогда, когда требуется сигнал, а не все время.
использование friend std::conditional<C, friendclass, void>::type;
где C
это ваше состояние. Друг, не относящийся к классу, будет игнорироваться.
Условный шаблон легко реализуется в C ++ 03. Однако, поскольку C ++ 03 не поддерживает друзей typedef, вам необходимо использовать следующий синтаксис
namespace detail { class friendclass {}; }
class Foo {
friend class std::conditional<C,
friendclass, detail::friendclass>::type::friendclass;
};
Обратите внимание, что в этом обходном пути подробное имя класса-пустышки должно совпадать с именем потенциального друга.
Объявление друга, которое не объявляет функцию, имеет одну из следующих форм:
друг разработал спецификатор типа;
простой указатель типа друга;
спецификатор typename друга;
поэтому невозможно объявить друзей класса без макроса.
Это кажется, к сожалению, это невозможно в компиляторе C ++: то есть кажется, что здесь может помочь только препроцессор. Примечание: у Йоханнеса есть предложение, поэтому есть надежда!
Однако я бы отметил, что:
нет причин не иметь безусловный дружба, но используйте ее, только если выполнены некоторые условия (статические или динамические).
Примечание: в будущем это то, что static_if предложение может охватывать.
Замечания: Johannes в значительной степени прибил это. В ’03 ты не сможешь подружиться
typedef — но если вы знаете, что у вас есть класс, то вы можете обратиться к
его injected class name
,
Ответ Йоханнеса также имеет преимущество использования стандартной функциональности библиотеки, что тоже всегда хорошо.
#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
всегда имеет
друг, но класс подружился меняется в зависимости от значения
вариант.
Интересный побочный вопрос заключается в том, является ли нарушение ODR иметь
версии Foo
как с, так и без some_compile_time_condition
установить на 1.
Я думаю, что вы берете 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
Пожалуйста, поправьте меня, если я неправильно понял вопрос.