How to make wrapper's constructors copy paste the underlying type's constructors?

94 Views Asked by At

I am writing a class stalker<Obj> that holds inside a variable of type Obj. I want stalker<Obj> to pretend that it is the same as Obj (from the user's perspective). Thus, I expect that stalker<Obj> is constructible like Obj.

template <typename Obj>
class stalker {
  Obj obj;
  // other variables

 public:
  template <typename... Args>
  stalker(Args&&... args) : obj(std::forward<Args>(args)...) {
  }
};

I implement only copy & move constructors additionally.

stalker<Obj> also has other variable(s) which require some specific logiс (independent from Obj) when created.

Obj can be marked final.

However, my approach fails on distinguishing std::initialiser_list and curly brackets object. The compiler says: "No matching constructor for initialization of 'std::vector<int>'".

int main() {
  stalker<std::vector<int>> v = {1, 2, 3};  // CE
  stalker<std::vector<int>> v({1, 2, 3});   // CE

  return 0;
}

How to reach stalker<Obj> maximal imitation of Obj in terms of construction?

Creating constructors from const Obj& and Obj&& fails: sometimes the compiler cannot conclude which of these constructors fits the best and in other cases it does not try to adapt {...} -> std::init_list -> Obj at all (just {...} -> Obj).

I added these constructors (is std::is_constructible enough?):

 template <typename T>
 requires (std::is_constructible_v<Obj, const std::initializer_list<T>&>)
 stalker(const std::initializer_list<T>& init_list) : obj(init_list) {
 }

 template <typename T>
 requires (std::is_constructible_v<Obj, std::initializer_list<T>&&>)
 stalker(std::initializer_list<T>&& init_list) : obj(std::move(init_list)) {
 }

However, now it compiles with std::vector but shows an error (and it does work with the raised error after all!):

struct A {
  int val;
};

int main() {
  stalker<A> a = {1};

  return 0;
}

Also, it does not convert inner {...} to std::initialiser_list.

int main() {
  stalker<std::vector<std::vector<int>>> v = {{1, 2, 3, 4},
                                              {5, 6, 7},
                                              {8, 9},
                                              {10}};

  return 0;
}
0

There are 0 best solutions below