Search code examples
c++c++11templatesinitializer-list

std::initializer_list: error C2064: term does not evaluate to a function taking 0 arguments


I have a template class called Vector which has an exactly three-member variable of type = template argument type.

I have learned about the initializer list constructor from here: (Brace-enclosed initializer list constructor). I wanted to apply this technique with the SFINE std::enable_if.

That means I want to construct an object if and only if the user provides three parameters to the Vector class's constructor.

Following is my attempt:

#include <initializer_list>
#include <type_traits>

template<typename T> class Vector
{
private:
    T m_x, m_y, m_z;
public:
    template<typename U = std::initializer_list<T>,
        typename std::enable_if_t<U::size() == 3>
    >
        constexpr Vector(const U &list)
    {
        auto iter = list.begin();
        m_x = *iter;
        m_y = *(++iter);
        m_z = *(++iter);
    }
};

int main()
{
    Vector<int> vec = { 1, 2, 3 };
    return 0;
}

But I am getting the following errors:

error C2064 : term does not evaluate to a function taking 0 arguments
note: see reference to class template instantiation 'Vector<int>' being compiled
error C2440 : 'initializing' : cannot convert from 'initializer list' to 'Vector<int>'
note: No constructor could take the source type, or constructor overload resolution was ambiguous

Here is the online result: https://godbolt.org/z/Njf6ym

My question is:

What is the error message saying about? I am a newbie, learning things from tutorials and books. I could not understand the meaning. Sorry, if its too obvious error message.

Can we restrict construction/ instantiation of the Vector class, if and only if, the user provides three arguments to the initializer_list constructor?


Solution

  • std::initializer_list<int>::size() is not a static member function.

    U::size() is invalid syntax when U is an initializer list.

    constexpr Vector(T const& a, T const& b, T const& c)
    {
        m_x = a;
        m_y = b;
        m_z = c;
    }
    

    your code compiles. You cannot restrict the number of elements you get in an initializer list constructor at compile time.