jeudi 30 avril 2015

Overload resolution issue in generic vector class

I have a generic vector class in which I've implemented a constructor that accepts a lambda. The idea being that the lambda is called to initialise each element in the vector, the lambda's single parameter being the element index.

However this is interfering with my "from scalar" constructor when passing a scalar of a different type than the vector's element type:

template <typename T, int N>
struct SomeVectorClass
{
    T values[N];

    SomeVectorClass() {}

    SomeVectorClass(T scalar)
    {
        for (int i = 0; i < N; i++) values[i] = scalar;
    }

    template <typename InitFunctionType>
    SomeVectorClass(InitFunctionType initFunction)
    {
        for (int i = 0; i < N; i++) values[i] = initFunction(i);
    }
};

...

SomeVectorClass<int, 2> a([&] (int i) { return i; }); // This works
SomeVectorClass<int, 2> b(123); // This works
SomeVectorClass<int, 2> c(123.f); // This causes error "called object type 'float' is not a function or function pointer"

What I was expecting for "c" was for the compiler to automatically cast 123.f to 123 and then call the "from scalar" constructor (which accepts an int in this case).

Three questions:

  1. Is the lambda constructor preferred by the overload resolution because it doesn't require casting?
  2. Is there a way to make this work without std::enable_if() or similar hacks?
  3. If not, how would I use std::enable_if() to only enable the lambda constructor if InitFunctionType is a lambda?

Thanks in advance for your time!

EDIT: Forgot to mention that I can't use std::function, for performance reasons. The class needs to be inline-friendly.

Aucun commentaire:

Enregistrer un commentaire