2

I would like to compile the code below with c++17, so that I can pass any function (lambda) that has a specific signature, int(int), while also allowing the default argument:

template <class F = int(int)> // for deduction
struct A{
        A(F f = [] (int x){return x;}) : f_{f} {}

        F f_;
};

int main() {
        A work([](int x){return x + 1;});
        A not_work; // compile error.
}

However, clang emits an error:

a.cpp:6:4: error: data member instantiated with function type 'int (int)'
        F f_;
          ^
a.cpp:11:4: note: in instantiation of template class 'A<int (int)>' requested here
        A not_work;
          ^

I don't understand why the member f_ can be initialized when I pass the lambda and the default lambda argument cannot be?

Meanwhile, is there any better way to do this?

1 Answer 1

3

As the error message said, you can't declare a data member with a function type like int(int).

When passing a lambda to the constructor, the template parameter F would be deduced as the lambda closure type by CTAD (since C++17); when passing nothing F will use the default argument int(int) and the data member f_'s type would be int(int) too, which causes the error.

You might use a function pointer type (lambdas without capture could convert to function pointer implicitly) or std::function<int(int)>. E.g.

template <class F = int(*)(int)> // for deduction
struct A{
        A(F f = [] (int x){return x;}) : f_{f} {}

        F f_;
};

Or

template <class F = std::function<int(int)>> // for deduction
struct A{
        A(F f = [] (int x){return x;}) : f_{f} {}

        F f_;
};
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, but I have another question. Then why the line A work([](int x){return x + 1;}); works? It seems strange to me that work and not_work object both take lambda as an argument in their ctor, while only one of them works.
@wk_j Because when you pass a lambda to A's constructor, F is deduced to be the anonymous lambda type rather than int(int), but when you supply no parameter the default of int(int) is used.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.