Ce problème m'est apparu à partir d'un autre morceau de code, mais il se résume à cet extrait de code:
clang++ -std=c++17 -Wall main.cpp && ./a.out;
main.cpp:13:18: error: no matching constructor for initialization of 'A'
A* ptr = new A; // how to call the constructor with a specific template argument ?
^
main.cpp:6:5: note: candidate template ignored: couldn't infer template argument 'I'
A() : _i{I} {}
^
main.cpp:3:8: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
struct A
^
Cela ne sera pas surprenant de générer l'erreur suivante:
#include <iostream>
struct A
{
template <int I>
A() : _i{I} {}
int _i;
};
int main()
{
A* ptr = new A; // how to call the constructor with a specific template argument ?
return 0;
}
Cela ressemble à un problème qui aurait été rencontré des milliers de fois auparavant, mais je n'ai pas trouvé la solution sur cppreference ou SO.
Comment spécifier les arguments de modèle du constructeur dans un nouveau expression?
3 Réponses :
Malheureusement, vous ne pouvez pas spécifier explicitement des arguments de modèle pour le modèle de constructeur, qui ne peut être utilisé que si les paramètres du modèle peuvent être déduits. [temp.arg.explicit] / 8 p >
[Remarque: étant donné que la liste d'arguments de modèle explicite suit le nom du modèle de fonction et que les modèles de constructeur ([class.ctor]) sont nommés sans utiliser de nom de fonction ([class.qual]), il n'y a aucun moyen de fournir une liste d'arguments de modèle explicite pour ces modèles de fonction. - note de fin]
Comme mentionné dans mon commentaire, une solution de contournement possible pourrait être d'utiliser l'héritage:
struct A
{
int _i;
};
template<int I>
struct B : A
{
B() : A::_i(I) {}
};
...
A* a = new B<10>;
Vous devez le déduire. Vous ne pouvez pas les transmettre explicitement.
Une solution pour votre exemple serait:
struct A
{
template <int I>
A(std::integral_constant<int, I>) : _i{I} {}
int _i;
};
auto a = A{std::integral_constant<int, 4>{}};
En effet, merci, ou en fonction de votre idée, je pourrais utiliser un «tag» factice comme celui-ci coliru.stacked -crooked.com/a/6ad797ec94427693 . Je pense que c'est ce que j'utiliserai pour mon cas.
Quel est le but d'utiliser un constructeur basé sur un modèle au lieu d'une classe basée sur un modèle? Peut-être que cela pourrait être résolu en utilisant l'héritage, où la classe enfant est un modèle?
@Someprogrammerdude Essentiellement, je veux fournir une sorte de vue sur un tableau typé et je veux pouvoir créer ces vues à partir de std :: tableaux de n'importe quelle taille (d'où le constructeur basé sur un modèle). Je pourrais fournir des détails si nécessaire. Mais ce n'est pas la question. : P Disons que je veux le faire, comment utiliser new si l'argument template du constructeur ne parvient pas à être déduit?