0

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?

UserUsing
  • 678
  • 1
  • 5
  • 16
  • You rarely actually need `std::initializer_list`. A normal constructor will be fine. `std::initializer_list` is for dynamic initialization lists. – Guillaume Racicot Feb 22 '19 at 20:48
  • *std::initializer_list is for dynamic initialization lists* that could be the reason why I could not do it in the above manner. – UserUsing Feb 22 '19 at 20:53

1 Answers1

2

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.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • Is there no way that I can make use `std::initializer_list` along with SIFINE technick to achieve the same result? Do I need to explicitly provide a constructor to do this? – UserUsing Feb 22 '19 at 20:10
  • @Using "You cannot restrict the number of elements you get in an initializer list constructor at compile time." This constructor is shorter than the one you wrote. Based on your follow up question, I suspect this is an X/Y problem, where you have a problem Y, found what you thought was a solution X, asked about X, and are now told that you cannot do X. Feel free to press the "ask question" button and ask about Y, the underlying problem (I'd guess your underlying problem is that the number `3` is actually a template parameter of `Vector`, but I could be wrong) – Yakk - Adam Nevraumont Feb 22 '19 at 20:37
  • Hmm... My issue though was to show a compiler error, when the user, provides more than 3 entries to the constructor BTW. As I am learning these new two concepts(SFINE and initializer_list constructor) I thought to apply here, in this case. – UserUsing Feb 22 '19 at 20:56