0

I'm trying to wrap std::function in a class with adds a readable string of the function name to std::function.

I did come up with this simple class (defined in header.hpp)

template <typename... Args>
class CExtended_Function
{
public:
    explicit CExtended_Function(
        const std::function<void(Args...)>& func_type, const std::string& func_name)
        : func(func_type)
        , function_name(func_name)
    {
    }

    /// Function
    const std::function<void(Args...)> func;

    /// Function Name
    const std::string function_name;
};

My own make function looks like this. The Idea is to pass the Function Name to the make function as a template argument. And the make function should create a std::function instance and a std::string instance.

(defined in header.hpp)

template <typename Func_T, typename... Args>
CExtended_Function<Args...> Make_Extended_Function()
{
    std::function<void(Args...)> func(Func_T);
    std::string func_name(NCommonFunctions::type_name<Func_T>());
    CExtended_Function<Args...> res(func, func_name);

    return res;
}

where type_name<My_Function>() returns the name of the function as std::string_view

defined in header.hpp

template <class T>
constexpr std::string_view type_name();

However when using my make function like this

used in source.cpp

static void Test_Callback();

auto test = Make_Extended_Function<Test_Callback>();

I'm getting the error :

Symbol 'Make_Extended_Function' could not be resolved

Could you give me a hint why I'm getting this error?

Dr.Death
  • 93
  • 9
  • Are you one of the many that tried to [implement a template in a .cpp file](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file)? – Quentin Jul 21 '19 at 12:16
  • nope all templates are defined and implemented in a header file. – Dr.Death Jul 21 '19 at 12:27
  • Does the problem go away if you put everything in a single file? – L. F. Jul 21 '19 at 13:31
  • I wrote this as an answer, but then I realized that this might not be the problem and deleted it. Regardless, you are passing the function as a type parameter, but it is not a type, please take a look at https://godbolt.org/z/NnESxJ . It this what you wanted to achieve? If you apply my fix, does it compile? – CuriouslyRecurringThoughts Jul 21 '19 at 14:48
  • @L.F. nope it was not an include problem. – Dr.Death Jul 21 '19 at 21:01

2 Answers2

1

a couple of things you may need to change in your code:

  1. Test_Callback is a function, you can only pass function pointer as a non-type template argument. I.e. it should be auto test = Make_Extended_Function<&Test_Callback>(); instead;
  2. If you're passing a function pointer as template argument, the syntax is template<function+pointer_type function pointer>(similar to template), so make_extended_function should be template <auto Func_T, typename... Args> CExtended_Function<Args...> Make_Extended_Function() instead (I use "auto" here to make things easier). And the same for type_name()

Sample code:

#include <iostream>
#include <functional>
#include <string_view>

using namespace std;
namespace NCommonFunctions {
template <auto T>
std::string type_name() { return "a_name"; }
}
template <typename... Args>
class CExtended_Function
{
public:
    explicit CExtended_Function(
        const std::function<void(Args...)>& func_type, const std::string& func_name)
        : func(func_type)
        , function_name(func_name)
    {
    }

    /// Function
    const std::function<void(Args...)> func;

    /// Function Name
    const std::string function_name;
};

template <auto Func_T, typename... Args>
CExtended_Function<Args...> Make_Extended_Function()
{
    std::function<void(Args...)> func(Func_T);
    std::string func_name(NCommonFunctions::type_name<Func_T>());
    CExtended_Function<Args...> res(func, func_name);

    return res;
}
 void Test_Callback() { cout << "test" << endl; }
int main () {
    auto test = Make_Extended_Function<&Test_Callback>();
    test.func();
}
SPD
  • 370
  • 2
  • 9
0

Make_Extended_Function expects types. you provide function pointer, so an error.

The easier fix would probably be to change Make_Extended_Function to:

template <typename... Args>
CExtended_Function<Args...>
Make_Extended_Function(const std::function<void(Args...)>& f, const std::string& name)
{
    return CExtended_Function<Args...>(f, name);
}

(but you have to call it with a std::function to allow deduction).

NCommonFunctions::type_name seems to have identical issues than Make_Extended_Function.

A probably better fix would be to drop std::function and take functor directly:

template <typename F>
class CExtended_Function
{
public:
    explicit CExtended_Function(
        const F& f, const std::string& name)
        : f(f)
        , name(name)
    {
    }

    F f;
    std::string name;
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302