C++ Использование точечного синтаксиса для вызова функции в "свойстве" (безымянный класс)

Цель

Моя цель позвонить 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++.

1 ответ

Для вложенного класса нет способа обойти репликацию интерфейса 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();
}
Другие вопросы по тегам