The template variational function in the template will not compile

I am trying to write a function for a template class that takes a parameter that is a function pointer for a member class inside the private data of a large class. When you call this member, it calls this function in a smaller class. (Invalid right?) To demonstrate, I have a non-working example:

#include <vector>
#include <iostream>

using namespace std;

template <typename T, typename C>
struct MyClass {

    template <typename F, typename... A>
    auto call_me(F func, A... args) { // pass in the function we want to call
        return (mContainer.*func) (args...); // call the function supplied by 
        // the parameter on the private member data
    }

    C mContainer; // this will be private in my actual code

};


int main() {
    MyClass<int, std::vector<int> > test;;

    cout << test.call_me(&std::vector<int>::size) << endl; // works
    test.call_me(&std::vector<int>::insert, test.mContainer.begin(), 4); // doesn't work

    return 0;
}

, , , . , size 'Private' ( ) vector class MyClass. , , insert ( ), :

.\template.cpp: In function 'int main()':
.\template.cpp:24:71: error: no matching function for call to 'MyClass<int, std::vector<int> >::call_me(<unresolved overloaded function type>, std::vector<int>::iterator, int)'
     test.call_me(&std::vector<int>::insert, test.mContainer.begin(), 4);
                                                                       ^
.\template.cpp:10:10: note: candidate: template<class F, class ... A> auto MyClass<T, C>::call_me(F, A ...) [with F = F; A = {A ...}; T = int; C = std::vector<int>]
     auto call_me(F func, A... args) { // pass in the function we want to call
          ^~~~~~~
.\template.cpp:10:10: note:   template argument deduction/substitution failed:
.\template.cpp:24:71: note:   couldn't deduce template parameter 'F'
     test.call_me(&std::vector<int>::insert, test.mContainer.begin(), 4);

, , , , . Variadic, .

+4
3

, insert . , , , . , , .

using insert_func_t = std::vector<int>::iterator(std::vector<int>::*)(std::vector<int>::const_iterator, const int&);
test.call_me(static_cast<insert_func_t>(&std::vector<int>::insert), test.mContainer.begin(), 4);

static_cast<return_type(class_name::*)(function_parameters)>(&class_name::function_name)

- , , .

template <typename T, typename C>
struct MyClass {

    template <typename F, typename... A>
    auto call_me(F func, A... args) { // pass in the function we want to call
        return func(mContainer, args...); // call the function supplied by 
        // the parameter on the private member data
    }

    C mContainer; // this will be private in my actual code
};

int main() {
    MyClass<int, std::vector<int> > test;;

    test.call_me([](auto& container, auto... args){ container.insert(args...); }, test.mContainer.begin(), 4);

    return 0;
}
+6

, , . , , yours std:: bind(), , , , . /p >

:

    using ftype = std::vector<int>::iterator(std::vector<int>::*)
        (std::vector<int>::const_iterator, const std::vector<int>::value_type&);
    test.call_me((ftype)(&std::vector<int>::insert), test.mContainer.begin(), 4); // works
0

It is easier to deal with function objects when doing this kind of thing. It unloads the problem of overloading the method to the compiler.

Lambdas also work (they are function objects):

#include <vector>
#include <iostream>

template <typename T, typename C>
struct MyClass {

    template <typename F, typename... A>
    auto call_me(F func, A&&... args) -> decltype(auto)
    { // pass in the function we want to call
        return func(mContainer, std::forward<A>(args)...); // call the function supplied by 
        // the parameter on the private member data
    }

    C mContainer; // this will be private in my actual code

};
/*
 * It often easier to deal in function objects
 */
struct insert
{
    template<class Container, class...Args>
    decltype(auto) operator()(Container& cont, Args&&...args) const
    {
        return cont.insert(std::forward<Args>(args)...);
    }
};

struct size
{
    template<class Container, class...Args>
    decltype(auto) operator()(Container& cont) const
    {
        return cont.size();
    }
};

int main() {
    MyClass<int, std::vector<int> > test;;

    std::cout << test.call_me(size()) << std::endl; // works
    test.call_me(insert(), test.mContainer.begin(), 4); // doesn't work

    // or lambdas
    auto insert2 = [](auto& container, auto&&...args) -> decltype(auto)
    {
        return container.insert(std::forward<decltype(args)>(args)...);
    };
    test.call_me(insert2, test.mContainer.begin(), 5); 


    return 0;
}
0
source

Source: https://habr.com/ru/post/1687440/


All Articles