Моя цель позвонить StaticLibrary::func()
из свойства (безымянный класс) в среде, используя синтаксис точки.
Например:
env.bar.func();
Я смог добиться static_cast<StaticLibrary>(env.bar).func();
, что близко, но синтаксис все еще слишком громоздок.
Можно ли выводить статическое приведение или я могу перегрузить некоторый оператор для получения желаемого синтаксиса?
НОТА: У меня есть ограничение, которое я не могу поставить
StaticLibrary
непосредственно как публичный членEnvironment
класс (объект, ссылка или указатель).
Я сейчас получаю ошибку (который я понимаю, но вставил сюда для полноты):
unnamedDotSyntax.cpp: In function ‘int main()’:
unnamedDotSyntax.cpp:48:13: error: ‘class Environment::<anonymous>’ has no member named ‘func’
env.bar.func();
^
Приведенный ниже пример является самой изощренной версией кода, который я могу предложить.
#include <iostream>
class StaticLibrary {
public:
int func (void) {
std::cout << "called " << __FUNCTION__ << std::endl;
}
};
class Environment {
public:
Environment (void) {
bar.sl = &sl;
}
inline
int foo (void) {
std::cout << "called " << __FUNCTION__ << std::endl;
}
class {
friend Environment;
public:
operator StaticLibrary & (void) {
return *sl;
}
private:
StaticLibrary * sl;
} bar;
private:
StaticLibrary sl;
};
int main (void) {
Environment env;
env.foo();
// Works
StaticLibrary sl = env.bar;
sl.func();
// Works, but the syntax is too cumbersome. Can the static cast be inferred somehow?
static_cast<StaticLibrary>(env.bar).func();
// unnamedDotSyntax.cpp:48:13: error: ‘class Environment::<anonymous>’ has no member named ‘func’
// env.bar.func();
env.bar.func();
}
НОТА: Это должно быть GCC-совместимым, а не Microsoft VC ++
Для вложенного класса нет способа обойти репликацию интерфейса StaticLibrary
потому что член оператора доступа (.
) не применяет никаких преобразований. Так называть func()
на bar
вам нужно иметь функцию-член func()
в bar
, Недостаточно, если bar
превращается в то, что имеет функцию-член func()
(потому что это может быть неоднозначным).
То есть вы можете обернуть интерфейс StaticLibrary
внутри bar
имея делегирующую функцию-член int func() { return sl.func(); }
или вы делаете bar
открытый элемент данных типа StaticLibrary
(что было запрещено вашим ограничением).
Здесь я дал вложенному классу имя, потому что это делает ошибки более читабельными, и я храню ссылку, а не указатель, потому что мне нравится семантика значений.
#include <iostream>
class StaticLibrary {
public:
int func() {
std::cout << "called " << __FUNCTION__ << std::endl;
return 0;
}
};
class Environment {
private:
StaticLibrary sl;
public:
class Bar {
friend Environment;
StaticLibrary& sl;
public:
explicit Bar(StaticLibrary& _sl) : sl(_sl) {};
operator StaticLibrary& () { return sl; }
int func() { return sl.func(); }
} bar;
Environment() : sl{}, bar{sl} {};
int foo() {
std::cout << "called " << __FUNCTION__ << std::endl;
return 0;
}
};
int main (void) {
Environment env;
env.foo();
// Works
StaticLibrary sl = env.bar;
sl.func();
// Works, but the syntax is too cumbersome. Can the static cast be inferred somehow?
static_cast<StaticLibrary>(env.bar).func();
// unnamedDotSyntax.cpp:48:13: error: ‘class Environment::<anonymous>’ has no member named ‘func’
// env.bar.func();
env.bar.func();
}
Других решений пока нет …