Domen Vrankar
Domen Vrankar

Reputation: 1743

using decltype for constructor parameters

I'm curious as to why the order of member declaration in this case is an issue:

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

while just changing the declaration order works:

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

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

Since both gcc and Clang handle it in the same manner I'd say that it's not a bug but I still find it confusing.

Upvotes: 2

Views: 683

Answers (1)

NathanOliver
NathanOliver

Reputation: 180965

This has to do with the completed-class context. A class is considered completed, only in:

  • function body ([dcl.fct.def.general]),

  • default argument,

  • noexcept-specifier, or

  • default member initializer

and the parmeter list of a member function is not a part of that. That means that any type you use needs to already be known (seen) by the compiler. In

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_ has not been seen yet, so you get a compiler error. With

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

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

b_ has been seen, so there is no error using it later on in the class.

Upvotes: 7

Related Questions