используя decltype для параметров конструктора - PullRequest
0 голосов
/ 07 марта 2020

Мне любопытно, почему порядок объявления членов в этом случае является проблемой:

class A
{
public:
    A(decltype(b_) b)
        : b_{b}
    {}

private:
    std::function<void(int, std::string, float)> b_;
};

// error: ‘b_’ was not declared in this scope

при простом изменении порядка объявления работает:

class A
{
    std::function<void(int, std::string, float)> b_;

public:
    A(decltype(b_) b)
        : b_{b}
    {}
};

Поскольку оба g cc и Clang обрабатывают это таким же образом, я бы сказал, что это не ошибка, но я все еще нахожу это запутанным.

1 Ответ

4 голосов
/ 07 марта 2020

Это связано с контекстом завершенного класса . Класс считается завершенным, только в:

  • теле функции ( [dcl.fct.def.general] ),

  • аргумент по умолчанию,

  • noexcept-specifier или

  • инициализатор элемента по умолчанию

и список параметров функции-члена не является частью этого. Это означает, что любой используемый вами тип должен быть уже известен (замечен) компилятором. В

class A
{
public:
    A(decltype(b_) b) <- class not complete here
        : b_{b}       <- class is complete here since the mem-initializer list is part of [dcl.fct.def.general]
    {}                <-/

private:
    std::function<void(int, std::string, float)> b_;
};

b_ еще не было замечено, поэтому вы получаете ошибку компилятора. С

class A
{
    std::function<void(int, std::string, float)> b_;

public:
    A(decltype(b_) b)
        : b_{b}
    {}
};

b_ было замечено, поэтому нет ошибок при использовании его позже в классе.

...