3

This works:

#include <functional>

template < bool (*F)( int ) > class Foo {};

bool fooFunc( int n ) { return true; }

int main( int argc, char* argv[] )
{
    auto a = Foo< fooFunc >();
}

but this doesn't work, because you can't convert the lambda to a function pointer:

#include <functional>

template < bool (*F)( int ) > class Foo {};

auto barFunc = [] ( int n ) -> bool { return true; };

int main( int argc, char* argv[] )
{
    auto a = Foo< barFunc >();
}

and this doesn't work, because you can't use a std::function<> as a template non-type parameter:

#include <functional>

template < std::function< bool( int ) > F > class Bar {};

auto barFunc = [] ( int n ) -> bool { return true; };

int main( int argc, char* argv[] )
{
    auto b = Bar< barFunc >();
}

So how do I create a template class that is able to accept a lambda enclosure as a template non-type parameter?

6
  • Note sure what you mean by non-type template parameter. Do you mean not simply putting template <typename T>? Is it because doing so relaxes the template parameter requirements too much for your needs? Commented Apr 23, 2013 at 21:41
  • 1
    He means a value (as opposed to a type) template parameter, e.g.: template <int N> Commented Apr 23, 2013 at 21:41
  • I think you are trying to do something at compile-time that can't be done in the general case until run-time, which is why "you can't use a std::function<> as a template non-type parameter" Commented Apr 23, 2013 at 21:52
  • If conversion from [](int)->bool to bool(*)(int) was constexpr, this would be easy to do. Commented Apr 23, 2013 at 22:09
  • To be clear, if the standard had said "The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator." constexpr instead of const this would be doable. But the standard was conservative. I cannot think of a technical reason why that conversion shouldn't be constexpr, can anyone else? Commented Apr 23, 2013 at 22:20

2 Answers 2

6

Just create a class template with a type parameter, and use decltype to deduce the type of the lambda when you instantiate the template.

#include <functional>

template <typename Function> 
class Bar 
{ };

auto barFunc = [] ( int n ) -> bool { return true; };

int main()
{
    auto b = Bar<decltype(barFunc)>();
}


But note that lambdas are not default constructible, so you'll probably need to add more code to create a constructor of Bar that takes in a copy of the lambda:

template <typename Function> 
class Bar 
{ 
    public:

    Bar(Function f) : m_function(f)
    { }

    private:

    Function m_function;
};
Sign up to request clarification or add additional context in comments.

Comments

0

In your first example, you need to add a pointer because the function did not decay into one.

int main( int argc, char** )
{
    auto a = Foo< std::add_pointer<decltype(fooFunc)>::type(0) >();
}

1 Comment

Interesting. Why is the (0) needed in std::add_pointer<decltype(fooFunc)>::type(0)?

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.