Come ho accennato nei commenti, se si pone questo problema, il mio primo approccio sarebbe quello di cambiare il problema stesso! A volte, invece di trovare una "soluzione difficile" per un "problema difficile", è meglio rendere il problema "più semplice"!
Non ci dovrebbe mai essere una necessità, in cui si deve scrivere FuncType<2, R(X,Y,Z)>::type
anziché semplice std::function<R(X,Y)>
.
Sopra è la mia vera risposta. Per risolvere il tuo problema come delizia del codice, sto mettendo una semplice risposta basata su macro. Invece del tempo di compilazione, ti darà il tipo richiesto in fase di pre-elaborazione.
#define F(R, ...) std::function<R(__VA_ARGS__)> // shorthand for std::function...
#define FuncType(N, R, ...) FUNC_##N(R, __VA_ARGS__) // Main type
#define FUNC_0(R, ...) F(R) // overload for 0 arg
#define FUNC_1(R, _1, ...) F(R, _1) // overload for 1 arg
#define FUNC_2(R, _1, _2, ...) F(R, _1, _2) // overload for 2 args
#define FUNC_3(R, _1, _2, _3, ...) F(R, _1, _2, _3) // overload for 3 args
Usage:
int main() {
static_assert(std::is_same<
FuncType(2, void, int, char, double, int), // <--- see usage
std::function<void(int, char)>
>::value, "!");
}
Come potete vedere c'è un piccolo cambiamento nell'uso. Invece di FuncType<2, void(int, char, double, int)>::type
, sto usando FuncType(2, void, int, char, double, int)
. Ecco lo demo.
A partire da ora, i FUNC_N
macro sono sovraccarico fino a 3 argomenti. Per ulteriori argomenti, se vogliamo evitare paste di copia, allora possiamo generare un file di intestazione con un semplice programma:
std::ofstream funcN("FUNC_N.h"); // TODO: error check for argv & full path for file
for(size_t i = 0, N = stoi(argv[1]); i < N; ++i)
{
funcN << "#define FUNC_" << i << "(R"; // FUNC_N
for(size_t j = 1; j <= i; ++j)
funcN << ", _" << j; // picking up required args
funcN << ", ...) "; // remaining args
funcN << "F(R"; // std::function
for(size_t j = 1; j <= i; ++j)
funcN << ", _" << j; // passing only relevant args
funcN <<")\n";
}
E semplicemente #include
esso:
#define F(R, ...) std::function<R(__VA_ARGS__)>
#define FuncType(N, R, ...) FUNC_##N(R, __VA_ARGS__)
#include"FUNC_N.h"
Ecco la demo per come genera il file di intestazione.
Nice Q & its solution. Sembra una delizia di codifica. Tuttavia, non riesco a capire, dove sarà usato praticamente? In una vera applicazione, perché qualcuno vorrebbe usare 'FuncType <2, void (int, char, double, int)> :: Type' invece di semplice' std :: function '! Anche all'interno dei modelli, non sembra esserci la necessità di fare una cosa del genere. Per risolvere un problema difficile ci sono 2 modi: o ricavare una soluzione altrettanto dura o semplificare il problema. :-) –
iammilind
@iammilind Ho avuto il problema durante un tentativo di progettare qualcosa con un mucchio di mixin. Uno dei mixin ottiene una lista variadica di tipi, l'ultimo dei quali è quello da cui ereditare. Va da sé che il primo 'N-1' deve essere usato come argomento per un tipo di funzione. :-) – skypjack