I wanted to move or assign a std::vector<Scalar>
into a std::vector<float>
depending on the type Scalar
.
If Scalar
is float
then move, else copy.
I tried this code
#include <vector>
using Scalar = double;
int main()
{
std::vector<Scalar> x(10);
std::vector<float> y(10);
if constexpr(std::is_same<Scalar, float>::value)
y = std::move(x); // line 11 (does not compile)
else
y.assign(x.begin(), x.end());
return 0;
}
but I get
main.cpp:11:24: error: no match for ‘operator=’ (operand types are ‘std::vector<float>’ and ‘std::remove_reference<std::vector<double>&>::type’ {aka ‘std::vector<double>’})
11 | y = std::move(x);
| ^
I thought that since std::is_same<Scalar, float>::value
is evaluated to false
at compile-time, then the line below would not be compiled.
I compiled it using g++ -std=c++17 main.cpp -o exec
.
How can I move/assign x
into y
depending on the Scalar
type?
As pointed out by HolyBlackCat in a comment, and as stated in cppref: "Outside a template, a discarded statement is fully checked." (https://en.cppreference.com/w/cpp/language/if).
Here is one potential solution involving one new template function
#include <vector>
template <typename U, typename V>
void move_or_copy(std::vector<U>& y, std::vector<V>&& x) {
if constexpr(std::is_same<U,V>::value) {
y = std::move(x);
} else {
y.assign(x.begin(), y.end());
}
}
using Scalar = double;
int main()
{
std::vector<Scalar> x(10);
std::vector<float> y(10);
move_or_copy(y, x);
return 0;
}