0

I tried to do the following :

template <typename T, int N>
struct Vector {
  T v[N];
  template<typename... Args> Vector(Args... args) : v { args... } {}
  template<typename S> Vector(Vector<S, N> const & V) : v {V.v} {}
};
int main() {
  Vector<float, 4> V (1.0f, 2.0f, 3.0f, 4.0f);
  Vector<float, 4> V2 (V);
  for (auto f : V2.v) { cout << f << ", "; } cout << endl;
  return 0;
}

And it worked (printed "1, 2, 3, 4, "), so I did not suspect anything until I tried to "specialize it" with :

  Vector(Vector const & V) : v {V.v} {}

or to use it with :

  Vector<double, 4> V2 (V);

And the compiler said :

error: cannot convert 'const float*' to 'float' in initialization

or the same with 'double'.

After that I tried simple arrays, and it failed with the same error, yet with enough templating it works..

Can someone please explain to me what is going on here?

3
  • You can't assign arrays, you need to loop over the elements copying them. Commented Mar 23, 2017 at 16:50
  • It's the same reason you can't write v1.v = v2.v; Commented Mar 23, 2017 at 16:50
  • Stop using dumb arrays and use std::array. It is practically the same as using an array, without all of the pitfalls you're seeing now, as this example shows Commented Mar 23, 2017 at 17:05

1 Answer 1

1

You can't initialize an array with another array.

No, it doesn't working with template copy constructor either, the following code snippet just gives the same error message.

template <class T, int N>
struct Vector2 {
  T vv[N];
};

template <typename T, int N>
struct Vector {
  T v[N];
  template<typename T1>
  Vector(const Vector2<T1, N> & V) : v{V.vv} {}
};

int main() {
  Vector2<float, 4> V2;
  Vector<float, 4> V1(V2);

  return 0;
}

The reason why your code snippet works is because that the compiler used the implicitly declared copy constructor. If you explicitly declare it as deleted or as private member, you will find out that the compiler doesn't even try to instantiate the template copy constructor, which I don't know why.

And I find that the V.v always decays to pointer, even if I try to cast it to T (&)[N] with reinterpret_cast. *reinterpret_cast<T (*)[N]>(V.v)

So... I try to find out an answer but it just lead to more questions...


A workaround can be wrapping the array into a class.

Sign up to request clarification or add additional context in comments.

2 Comments

Nice, and thanks, but I am looking for an explanation why it does work with additional templating. Also, note that classes with reference members are non-copyable (undefined behaviour, I think), so I would never do that, although it's sometimes tempting.
@elad Don't worry about the reference, you can remove it if want to use implicit copy-control members. And if you want to keep the reference, just define your own copy-control members.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.