1

I've defined a class template and a function,

template <typename F> class Base {
    public:
        Base(F ff): f(ff) {}
        template <typename... Ps> auto operator() (Ps... ps) const -> decltype(f(ps...)) { return f(ps...); }
    private:
        // f is a pointer to function
        F* f;   
};

int f(int i, int j) 
{
    return i + j;
}

int main()
{
    using f_type = remove_reference<decltype(f)>::type;
    Base<f_type> b{f};
    b(2, 5); // [Error] no match for call to '(Base<int(int, int)>) (int, int)'
}

the labeled error was reported. But when I changed the order of member variable of class Base, like:

template <typename F> class Base {
    private:
        // f is a pointer to function
        F* f;   
    public:
        Base(F ff): f(ff) {}
        template <typename... Ps> auto operator() (Ps... ps) const -> decltype(f(ps...)) { return f(ps...); }
};

It can compile.

What's the reason of these two different results? Thank you for your time!

Vogel_guo
  • 51
  • 2
  • 8

1 Answers1

1

Declarations are introduced in C++ in the order they are seen in the source. The notable exception where things are different are the bodies of member functions: when member functions are defined within the class declaration, the definition (but not its declaration) behaves as if the function is defined immediately after the class definition.

Since the rules about the location of member definitions does not apply to the declarations names used in the member function declaration need to be declared at this point. Changing the location of the member provides the necessary declaration.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • You mean before I declare and define a member function within class, the member variables I will use must be defined beforehand? Or I should define the member function outside the class? – Vogel_guo Dec 25 '16 at 21:54
  • @Vogel_guo: it doesn't matter where you *define* a member function. However, the names you refer to in its *declaration* need to be known when used (or need to be functions on dependant names). It is just the same with type names: you can't refer to a type defined only later from a [member] function declaration. – Dietmar Kühl Dec 25 '16 at 21:58
  • now I see. I shouldn't use an undefined name in member function declaration, but I can use a member variable defined after member function in the definition of it. right? – Vogel_guo Dec 25 '16 at 22:12
  • @Vogel_guo: the member function definitions which scoped inside the class definition behave as if they are actually define directly *after* the class definition. That is, *inside* the member function definition the corresponding class if a complete type which is **not** the case within the class definition itself. – Dietmar Kühl Dec 25 '16 at 22:28