Writing constructor of template class with template argument-depending parameters

£可爱£侵袭症+ 提交于 2019-12-13 03:44:14

问题


Consider the following two classes with constructors that accept wildly different sets of parameters.

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

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

Now, I want to write a class template TpC that will have an object (which might be A or B or something else). In other words, I want to be able to use the following:

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

How can I write a constructor for TpC that is dependent on the parameters of the constructors of A and B? It would be acceptable to write something like a trait/policy to tell TpC what the parameters should be for each particular specialization.


回答1:


You would need to use a template constructor. However, in order to prevent this constructor being called instead of the copy constructor, you need to add a bit of disambiguation. For example:

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)...) {}
};

In C++17 in_place is available in std.




回答2:


You could write a template constructor with parameter pack for TpC. (As the comments suggested I used SFINAE to constrain template, otherwise it might be better match than copy constructor. See the whole code snippet from the link I posted.)

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)...) {}
};

and then

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

LIVE




回答3:


If you are using c++11 or later, you can use a variadic template constructor with a parameter pack expansion calling std::forward on the constructor arguments. Something like:

template <typename T>
class TpC {
    T base;
public:
    template <typename... Args>
    TpC(Args&&... args)
    : base(std::forward<Args>(args)...) {
    }
};


来源:https://stackoverflow.com/questions/50492960/writing-constructor-of-template-class-with-template-argument-depending-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!