Sto provando a scrivere una metafunzione di nome signature_of che, dato il tipo di funzione (puntatore), functor o lambda, restituisce la sua firma.Come ottenere la firma di un'espressione di collegamento C++ (...)
Ecco quello che ho finora:
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/function_types/is_member_function_pointer.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <type_traits>
template <typename F>
struct signature_of_member
{
typedef typename boost::function_types::result_type<F>::type result_type;
typedef typename boost::function_types::parameter_types<F>::type parameter_types;
typedef typename boost::mpl::pop_front<parameter_types>::type base;
typedef typename boost::mpl::push_front<base, result_type>::type L;
typedef typename boost::function_types::function_type<L>::type type;
};
template <typename F, bool is_class>
struct signature_of_impl
{
typedef typename boost::function_types::function_type<F>::type type;
};
template <typename F>
struct signature_of_impl<F, true>
{
typedef typename signature_of_member<decltype(&F::operator())>::type type;
};
template <typename F>
struct signature_of
{
typedef typename signature_of_impl<F, std::is_class<F>::value>::type type;
};
E 'piuttosto semplice, con la maggior parte del lavoro vero e proprio stato fatto dalla libreria boost :: function_types. L'idea generale è:
- uso std :: is_class di discriminare tra le funzioni built-in (tra cui lambda) e funtori
- per i tipi di funzioni built-in, uso boost :: :: function_types tipo_funzione per ottenere la sua firma
- per funtori, ottenere il tipo di loro operatore(), ottenere la sua firma, e medico per rimuovere il "questo" parametro
questo funziona per le funzioni built-in:
int f(int);
typedef signature_of<decltype(f)>::type Sig; // Sig is int(int)
per lambda:
auto f = [](int) { return 0; }
typedef signature_of<decltype(f)>::type Sig; // Sig is int(int)
e per funtori:
struct A
{
int operator()(int);
};
typedef signature_of<A>::type Sig; // Sig is int(int)
Tuttavia, non funziona per bind() espressioni (che sono un caso particolare di funtori). Se provo questo:
#include <functional>
int g(int);
typedef signature_of<decltype(std::bind(g, 0))>::type Sig;
ottengo un errore di compilazione:
In file included from test.cpp:3:0:
signature_of.hpp: In instantiation of 'signature_of_impl<
_Bind<int (*(int))(int)>, true
>':
signature_of.hpp:45:74: instantiated from 'signature_of<
_Bind<int (*(int))(int)>
>'
test.cpp:21:52: instantiated from here
signature_of.hpp:39:74: error: type of '& _Bind<
int (*)(int)({int} ...)
>::operator()' is unknown
Il problema è che l'operatore() del funtore restituito da bind() è un modello, e quindi il suo tipo non può essere determinato.
È possibile ottenere la firma di un'espressione bind() in un altro modo?
VC10 non può compilare questo, gli errori sono stupidi come al solito ('errore C2039: 'tipo': non è un membro di 'boost :: function_types :: result_type''), non gli piace questa specializzazione: 'typedef typename signature_of_member :: tipo tipo; ' –
@Andy T: come si converte in std :: function senza menzionare il parametro template di std :: function, che * è * la firma ? – HighCommander4
sì, colpa mia, cancellazione ... –