47 votes

Modèles de modèles Variadic et transfert parfait

Cette question sur l' objet générateur de modèle m'a fait penser à des façons de l'automatiser.

Essentiellement, je veux automatiser la création de fonctions comme l' std::make_pair, std::bind1st et std::mem_fun , de sorte qu'au lieu d'avoir à écrire une fonction différente pour chaque modèle type de classe, vous pouvez écrire une seule variadic template modèle de la fonction qui gère tous les cas à la fois. L'utilisation de cette fonction serait:

make<std::pair>(1, 2);         // equivalent to std::make_pair(1, 2)
make<std::binder2nd>(&foo, 3); // equivalent to std::bind2nd(&foo, 3);

Est-il possible d'écrire cette fonction make? J'ai essayé ceci, mais il ne fonctionne pas dans GCC 4.5 ou 4.6:

template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
    return TemplateClass<Args...>(std::forward<Args>(args)...);
}

Si j'essaie de les appeler (e.g) make<std::pair>(1, 2) je viens d'obtenir

error: no matching function for call to 'make(int, int)'

J'ai obtenu la syntaxe de mal n'importe où ici?
Ou est ce droit et GCC est le problème?
Ou est-ce juste fondamentalement impossible en C++0x?

[modifier]

Proposition N2555 semble suggérer que ce qui est permis et GCC prétend avoir mis en œuvre dans GCC4.4.

38voto

Johannes Schaub - litb Points 256113

C'est exactement ça. Je m'attendrais à ce que cela fonctionne. Je pense donc que GCC a tort de rejeter cela. FWIW:

 #include <utility>

template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
    return TemplateClass<Args...>(std::forward<Args>(args)...);
}

int main() {
  make<std::pair>(1, 2);
}


// [js@HOST2 cpp]$ clang++ -std=c++0x main1.cpp
// [js@HOST2 cpp]$
 

7voto

Luc Danton Points 21421

Il s'agit probablement d'une bizarrerie du CCG. Je peux faire fonctionner les éléments suivants avec un instantané de développement (je n'ai pas de copie de 4.6 pour le moment):

 template<
    template<typename...> class TemplateClass
    , typename... Args

    , typename Result = TemplateClass<Args...>
    // Also works with the arguably more correct
    // , typename Result = TemplateClass<
    //     typename std::decay<Args>::type...
    // >
>
Result
make(Args&&... args)
{ /* as before */ }
 

3voto

Puppy Points 90818

C'est tout à fait faux - prendre en make_shared, par exemple. Le point de make_shared est qu'il existe au moment de l'exécution des gains d'efficacité pour l'utiliser. Mais qu'arriverait-il si j'ai essayé d'utiliser make<std::shared_ptr>? Ne pense pas que serait tout à fait. Ou que diriez-types où seule une partie des arguments du constructeur sont des arguments de modèle, et le reste ne le sont pas? Par exemple, make<std::vector, int>(other_vector.begin(), other_vector.end()); - les types d'itérateurs ne pas participer, mais vous les transmettre, de toute façon.

Il est impossible d'écrire un générique make fonction.

Comme pour la Norme, bien, il pourrait facilement avoir été retiré depuis. Vous devez vérifier la FDIS.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X