Je suis tenté de créer une surcharge de fonction afin qu'elle ne lie (fonctionne) qu'à une fonction membre. Je pris un coup d'oeil à la signature de la fonction de std::mem_fn
http://en.cppreference.com/w/cpp/utility/functional/mem_fnSyntaxe de modèle pour ne remplacer que les fonctions membres
template <class Ret, class T>
/* unspecified */ mem_fn (Ret T::* pm);
Je structuré mes paramètres en tant que tels
template <typename R, typename F>
auto call_me(R C::* func) {
return (mContainer.*func);
}
Cependant, je puis obtenir cette erreur
.\template.cpp: In function 'int main()':
.\template.cpp:29:49: error: no matching function for call to 'MyClass<int, std::vector<int> >::call_me(std::vector<int>::size_type (std::vector<int>::*)() const noexcept)'
cout << test.call_me(&std::vector<int>::size) << endl;
^
.\template.cpp:16:10: note: candidate: template<class R, class F> auto MyClass<T, C>::call_me(R C::*) [with R = R; F = F; T = int; C = std::vector<int>]
auto call_me(R C::* func) {
^~~~~~~
.\template.cpp:16:10: note: template argument deduction/substitution failed:
.\template.cpp:29:49: note: couldn't deduce template parameter 'F'
cout << test.call_me(&std::vector<int>::size) << endl;
La raison pour laquelle je Je suis en train de faire cela est donc je peux avoir une surcharge qui fonctionne pour les objets lambda et fonctionnels généraux et une autre surcharge qui fonctionne pour membe r pointeurs fonctionnels. Voici un exemple minimal de ce que j'essaie d'accomplir. Je sais que cette question prête un peu à confusion, alors n'hésitez pas à demander des éclaircissements si nécessaire.
#include <vector>
#include <iostream>
using namespace std;
template <typename T, typename C>
struct MyClass {
// This doesnt work because of SFINAE
template <typename F, typename... A>
auto call_me(F func, A... args) { // lambda version
return func(args...);
}
template <typename R, typename F>
auto call_me(R C::* func) { // member function version
return (mContainer.*func);
}
C mContainer; // this is private in my actual code
};
int main() {
MyClass<int, std::vector<int> > test;;
// these two calls will call the member function version of the overload
cout << test.call_me(&std::vector<int>::size) << endl;
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);
// this call will call the lambda version of the overload
cout << test.call_me([](std::vector<int>& in){ in.push_back(5); });
return 0;
}
'std :: invoke' fournit une syntaxe uniforme des appels. Si vous ne l'avez pas encore dans votre bibliothèque standard, il n'a pas besoin de fonctionnalités C++ 17 pour écrire, et il existe des implémentations distinctes. En ayant une fonction 'invoke', vous n'avez pas besoin de polluer le reste du code avec les différences d'appel. – chris
@chris Je viens de vérifier cela, ça me laisse toujours le problème de savoir si le paramètre fourni est une fonction membre ou un objet appelable. – Aryan
@IgorTandetnik hmm, je l'ai essayé avec ça aussi, mais ça ne marche toujours pas R (C :: * func)() 'et avec R (C :: * func) (Args ...)' avec 'Args' étant un autre paramètre de template – Aryan