0

I have this type in the header MyType.hpp:

struct MyType
{
    template<typename T>
    void operator(T t)
    {
        auto lamdba = [t](auto i){ t.someCall(i); };
        someMethod(lamdba);
    }

    template<typename L>
    void someMethod(L);
};

So, someMethod gets called with a generic lambda which accepts a generic parameter. Is it somehow possible to provide an implementation in MyType.cpp for someMethod? This does not work:

template<typename L>
void MyType::someMethod(L lambda)
{
    lambda(42);
    lambda("42");
    // etc...
}

As partial specialization is not allowed(only full specialization for function templates), is there any other way to "pass" the lambda of the header file to the implementation file MyType.cpp? If passing is not possible, maybe there exists a way of dynamically storing this lambda in MyType.hpp and access it in MyType.cpp?

max66
  • 65,235
  • 10
  • 71
  • 111
Juergen
  • 3,489
  • 6
  • 35
  • 59
  • 1
    Templates must be defined in headers (informally speaking). – molbdnilo Feb 14 '20 at 11:40
  • This doesn't compile even in [single source](https://godbolt.org/z/bcSs7k). Please provide [mcve] where everything works in header file, then ask how to move stuff to cpp. – Marek R Feb 14 '20 at 11:42
  • 1
    @MarekR: You wrongly feed the hole [Demo](https://godbolt.org/z/faDV-A) (missing `const`). – Jarod42 Feb 14 '20 at 11:47
  • @Jarod42 yes you right, but there is [more then one way to fix it](https://godbolt.org/z/NdcVJF) and the OP should first define what he exactly needs. – Marek R Feb 14 '20 at 11:51
  • Yes in general templates should be defined in headers, but there are some tricks in corner cases, where template can be limited to specific types and some template methods can be moved to cpp. – Marek R Feb 14 '20 at 11:54

2 Answers2

1

Every lambda has its own type. You will not be able to write down the type in your source code anyway.

As the translation unit which has the definition of your template will never see the lambda type, the template will never be instantiated. And you will not be able to get the type of a lambda to make it a specialization nor to have it for a manual instantiation.

As this the answer is: You can't use a lambda closure as parameter for a template specialized or manually instantiated if the template is visible only in its own translation unit.

Klaus
  • 24,205
  • 7
  • 58
  • 113
1
template<typename L>
void MyType::someMethod(L lambda)
{
    lambda(42);
    lambda("42");
    // etc...
}

Will not work. Templates (and lambda's) must be completely defined when instantiated. You cannot have a generic template definitions in .cpp - only full specializations can be implemented in .cpp (informally speaking). There are multiple ways to work around this. Brute force method would be to add in specializations for every type (perhaps calling a common template that only lives in the .cpp). Another approach could maybe be to use some kind of abstract factory design (returning interface based on the dispatched type) - but there is too little information here wrether that is a feasible solution.

darune
  • 10,480
  • 2
  • 24
  • 62