Il seguente codice in grado di risolvere il problema dell'ambiguità:
#include <iostream>
#include <string>
// Helper class providing a function call
template <typename T>
class PrintHelper
{
protected:
void print_impl(const T& t) { std::cout << t << std::endl; }
};
// Provides a print method for each type listed
template <typename... Ts>
class Printer : public PrintHelper<Ts>...
{
public:
template <typename U>
void print(const U& u) {
PrintHelper<U>::print_impl(u);
};
};
int main()
{
Printer<int, std::string> p;
p.print(std::string("Hello World")); // Ambiguous Call
}
Il che non è molto bello a causa di il requisito che il tipo U (dedotto in chiamata) sia esattamente uno di th e tipi nella lista dei tipi variadici. Potresti essere in grado di fantasticare un po 'per risolvere quel problema. Con un po 'di template magic e Sfinae, puoi probabilmente risolverlo abbastanza facilmente (ma non è sicuramente così pulito e ordinato).
Il problema dell'ambiguità non è correlato all'utilizzo di modelli template o variadic, ovviamente è un'applicazione diretta delle regole di ricerca dei membri (Sezione 10.2/2 dello standard), ovvero, il cosiddetto "regole per nascondere i membri". Se si prende questa versione non-modello più semplice, si otterrà lo stesso problema di ambiguità, ma con una soluzione molto semplice ad esso:
struct IntPrinter {
void print(const int& i) { std::cout << i << std::endl; };
};
struct StringPrinter {
void print(const std::string& s) { std::cout << s << std::endl; };
};
struct IntStringPrinter : IntPrinter, StringPrinter {
using IntPrinter::print; // These using-statements will solve the problem
using StringPrinter::print; // by importing all 'print' functions to the same
// overload resolution level.
};
Quindi, il problema qui è davvero che l'ambiguità si pone prima il compilatore anche tentativi applicare le normali regole di risoluzione del sovraccarico, perché prima cerca di capire quale ramo dell'ereditarietà seguire per trovare le funzioni membro, e quindi risolverà il sovraccarico solo a livello di ereditarietà. E il problema quando si usano i modelli variadic è che non sembra esserci un modo per decomprimere un insieme di istruzioni "using" per importare tutte le funzioni di stampa fino allo stesso livello di ereditarietà. Se qualcuno conosce un modo per scartare tali dichiarazioni d'uso, sono tutto orecchie. Potrebbe essere necessario ricorrere a soluzioni di modelli pre-variadici (come un modello generale con 10 argomenti e specializzato per tutte e dieci le versioni).
fonte
2012-12-13 17:47:23
Stesso problema con gcc 4.7.2 (in [liveworkspace (http://liveworkspace.org/code/1a4YN8$0)). Grazie per l'esempio copy/pastable btw. –
clang 3.2 trunk 165721 dice: 'errore: membro 'print' trovato in più classi base di diversi tipi' – user786653
Vedere anche [questa domanda] (http://stackoverflow.com/questions/5368862/why-do-multiple-edherited -Funzioni-con-stesso-nome-ma-diverse-firme-no). Questo è essenzialmente un problema della combinazione di regole nascoste e delle funzionalità molto limitate di decomprimere argomenti di template variadic. –