Considérez les deux classes suivantes avec des constructeurs qui acceptent des ensembles de paramètres très différents.

class A {
public:
  A(int x, double y) {
    //do something
  }
};

class B {
public:
  B(const std::vector<bool>& x) {
    //do something
  }
};

Maintenant, je veux écrire un modèle de classe TpC qui aura un objet (qui pourrait être A ou B ou autre chose). En d'autres termes, je souhaite pouvoir utiliser les éléments suivants:

int x;
double y;
std::vector<bool> z;
TpC<A> obj_a (x, y);
TpC<B> obj_b (z);

Comment puis-je écrire un constructeur pour TpC qui dépend des paramètres des constructeurs de A et B? Il serait acceptable d'écrire quelque chose comme un trait / une politique pour dire à TpC quels devraient être les paramètres pour chaque spécialisation particulière.

0
Jaeya 23 mai 2018 à 19:07

3 réponses

Meilleure réponse

Vous devrez utiliser un constructeur de modèle. Cependant, pour éviter que ce constructeur ne soit appelé à la place du constructeur de copie, vous devez ajouter un peu d'homonymie. Par exemple:

template<class T>
class TpC {
     T t;
public:
     struct in_place_t { };
     static constexpr in_place_t in_place;
     template<class... ARGS>
     TpC(in_place_t, ARGS... args) : t(std::forward<ARGS>(args)...) {}
};

En C ++ 17 in_place est disponible dans std.

2
SergeyA 23 mai 2018 à 16:23

Vous pouvez écrire un constructeur de modèle avec le pack de paramètres pour TpC. (Comme le suggèrent les commentaires, j'ai utilisé SFINAE pour contraindre le modèle, sinon cela pourrait être meilleure correspondance que copier le constructeur. Voir l'extrait de code complet du lien que j'ai publié.)

template <typename T, typename... U>
struct my_is_same {
    constexpr static bool value = false;
};
template <typename T1, typename T2, typename... U>
struct my_is_same<T1, T2, U...> {
    constexpr static bool value = std::is_same_v<T1, std::remove_cvref_t<T2>>;
};
template <typename T, typename... U>
inline constexpr bool my_is_same_v = my_is_same<T, U...>::value;

template <typename T>
class TpC {
    T t;
public:
    template <typename... Args, typename = std::enable_if_t<
                                             !my_is_same_v<TpC, Args...> &&
                                             std::is_constructible_v<T, Args&&...>
                                           >>
    TpC(Args&& ... args) : t(std::forward<Args>(args)...) {}
};

Puis

int x;
double y;
std::vector<bool> z;
TpC<A> obj_a (x, y);
TpC<B> obj_b (z);

VIVRE

3
songyuanyao 24 mai 2018 à 02:19

Si vous utilisez c ++ 11 ou version ultérieure, vous pouvez utiliser un constructeur de modèle variadique avec une extension de pack de paramètres appelant std :: forward sur les arguments du constructeur. Quelque chose comme:

template <typename T>
class TpC {
    T base;
public:
    template <typename... Args>
    TpC(Args&&... args)
    : base(std::forward<Args>(args)...) {
    }
};
-1
flamewing 23 mai 2018 à 17:00