I am trying to build a constructor to take an array as an argument which overloads another who take a scalar instead. Code is below.
#include <iostream>
template <typename T>
class SmallVec { // This is a 3 dimensional vector class template
public:
T data[3] = {0}; // internal data of class
template <typename U>
explicit SmallVec(const U& scalar) { // if a scalar, copy it to each element in data
for(auto &item : data) {
item = static_cast<T>(scalar);
}
}
template <typename U>
explicit SmallVec(const U* vec) { // if a vector, copy one by one
for(auto &item : data) {
item = static_cast<T>(*vec);
vec++;
}
}
};
int main() {
float num = 1.2;
float *arr = new float[3];
arr[2] = 3.4;
SmallVec<float> vec1(num); // take num, which works fine
SmallVec<float> vec2(arr); // !!!--- error happens this line ---!!!
std::cout << vec1.data[2] << " " << vec2.data[2] << std::endl;
return 0;
}
The compiler complains that
error: invalid static_cast from type 'float* const' to type 'float'
Obviously, vec2(arr)
still calls the first constructor. However, if I remove template <typename U>
and replace U
to T
. The program just works fine. What should I do to correct this?
Any suggestions are appreciated!
Here's how to use SFINAE to get what you want:
#include <vector>
#include <map>
#include <string>
using namespace std;
template<class T>
struct Foo {
template <class U, typename enable_if<is_pointer<U>::value, int>::type = 0>
Foo(U u){}
template <class U, typename enable_if<!is_pointer<U>::value, int>::type = 0>
Foo(U u){}
};
int main()
{
Foo<int> f('a'); // calls second constructor
Foo<int> f2("a"); // calls first constructor
}
live: https://godbolt.org/g/ZPcb5T
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With