Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ class template constructor -- overload reference(U&) with array(U*) failed

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!

like image 262
astroboylrx Avatar asked Apr 24 '16 07:04

astroboylrx


1 Answers

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

like image 163
xaxxon Avatar answered Sep 29 '22 08:09

xaxxon