Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ pass function as template argument within constructor

I’d like to replace a std::function with a template parameter, since everything is known at compile time.
No I know there a many answers here in the forum and over the internet how to pass and directly consume a templated function (for ex here https://rules.sonarsource.com/cpp/RSPEC-5213/?search=std%3A%3Afunction)

However in my case: I am using the templated function in a private member. Therefore I have to set up the templated function within the constructor.

Now I have 2 questions:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  1. how can I pass and store the templated function as a member parameter for later use in a private function

  2. is it possible to use concepts to enforce that all functions passed as a template argument are using a specific signature (in my case std::string(const uint32_t u32ReadOffset, const uint32_t u32MaxReadLength))

So far i have come up with this

#include <string_view>
#include <concepts>
#include <string>
#include <cstdint>

template <typename T, typename U, typename V>
concept IDmmy = requires(T a, const std::string_view b)
{
  { a.template foo<U>() };
  { a.template bar<V>(b) };
};


template<typename FnGetFunction_T>
class Foo
{
    public:
    explicit Foo(FnGetFunction_T fn);
    
    void publicFunction();
    
    private:
    
    FnGetFunction_T m_fn;
    
    void privateFunction();
};


template<typename FnGetFunction_T>
Foo<FnGetFunction_T>::Foo(FnGetFunction_T fn):
m_fn(fn)
{
    
}

template<typename FnGetFunction_T>
void Foo<FnGetFunction_T>::publicFunction()
{
    //do some checking first
    //call private function
    privateFunction();
}

template<typename FnGetFunction_T>
void Foo<FnGetFunction_T>::privateFunction()
{
    //collect some internal data
    std::string strRes = m_fn(0,0);
    //do something with strRes
}

static std::string DummyRead(const uint32_t u32Offset, uint32_t u32MaxReadLength)
{
    if(0 != u32Offset && 0 != u32MaxReadLength)
    {
        //avoid compiler warning in this mock
    }
    return "";
}


int main()
{
    Foo<decltype(DummyRead)> foo = Foo<decltype(DummyRead)>(DummyRead);
    return 0;
}

https://coliru.stacked-crooked.com/

Unfortunately this gives me a compiler error invalidly declared function type.
Could you help me how to fix this?

Also is it possible to enforce which concepts that FnGetFunction_T always looks like this
std::string(const uint32_t u32Offset, uint32_t u32MaxReadLength) ?

thx once again guys for your help 🙂

>Solution :

Functions are not like other objects. When you pass a function as arugment you pass a function pointer not the function itself.

If you fix that:

Foo<decltype(&DummyRead)> foo = Foo<decltype(&DummyRead)>(DummyRead);

The code compiles: https://godbolt.org/z/Tv1ceqYzs

However, with Class Template Argument Deduction (CTAD) and making use of function to pointer to function decay it simply becomes:

Foo foo = Foo(DummyRead);

Live Demo


Also is it possible to enforce which concepts that FnGetFunction_T always looks like this std::string(const uint32_t u32Offset, uint32_t u32MaxReadLength) ?

If that is what you want then there is no point in making the type of the function a template argument in the first place. You can use usign function_type = std::string(uint32_t,uint32_t) as the type of the function.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading