'C++ 20 lambda in template: unable to deduce ‘auto*’ from lambda

Given the following simple wrapper struct (inspired by this answer):

template <auto* F> struct Wrapper;

template <class Ret, class... Args, auto (*F)(Args...) -> Ret>
struct Wrapper<F>
{
    auto operator()(Args... args) const
    {
        return F(args...);
    }
};

The following works:

int this_works(){
    return 42;
}
int main(){
    return Wrapper<this_works>()();
}

But I want this, using c++ 20:

int main(){
    return Wrapper<[](){return 42;}>()();
}

g++-11 --std=c++20 and clang++13 --std=c++20 both complain about the latter with some hard to decipher error messages, including:

  • mismatched types ‘auto*’ and ‘main()::<lambda()>
  • error: non-type template parameter 'F' with type 'auto *' has incompatible initializer

Is there a way to make the second example work? I tried a constexpr function pointer to the lambda but it complained about it having no linkage ...



Solution 1:[1]

Wrapper expects function pointer, but template argument deduction won't consider implicit conversion (from lambda without capture to function pointer).

You can convert the lambda to function pointer explicitly:

int main(){
    return Wrapper<static_cast<int(*)()>([](){return 42;})>()();
}

or

int main(){
    return Wrapper<+[](){return 42;}>()();
}

LIVE

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1