Got a parametrized constructor which accepts size_t variables, and therefore should be called when trying to create an object passing a size_t variable. Instead, compiler tries to call the initializer_list<value_type>
constructor, tries to convert the size_t
to double, fails and throws an error:
error: non-constant-expression cannot be narrowed from type 'size_t' (aka 'unsigned long') to 'double' in initializer list [-Wc++11-narrowing] Vector whyMe{u};
It does differentiate between String
and initializer_list
when choosing a constructor, any random integer will still be converted to list of doubles tho, which is also strange as tagging a constructor with explicit (explicit Vector (std::initializer_list<value_type> list)
), at least as I understand it, should only allow instances of initializer_list<...>
in. Would be grateful for a fix, that doesn't use explicit though, as it may be detrimental to further development.
#include <iostream>
class Vector {
public:
using value_type = double;
private:
size_t sz;
size_t max_sz;
value_type* values;
public:
// Constructors
// parametrized
Vector (std::initializer_list<value_type> list)
: sz{list.size()}, max_sz{list.size()}, values{new value_type[list.size()]} {
int tempIterator = 0;
for (value_type el : list) {
values[tempIterator] = el;
++tempIterator;
}
std::cout << "std::initializer_list<value_type> list constructor called" << std::endl;
}
Vector(size_t n)
: sz{0}, max_sz{n}, values{new value_type[n]} {
std::cout << "size_t n constructor called" << std::endl;
}
Vector (std::string n): sz{0}, max_sz{0}, values{new value_type[0]} {
std::cout << "string constructor called " << n << std::endl;
}
// Destructors
~Vector() {
delete[] values;
}
};
int main () {
std::initializer_list<double> love{1,2,3,4,5,6};
size_t u{5};
std::string compiler{"idontwanttolive"};
Vector wannaDie{love};
Vector whyMe{u};
Vector lifeIsNotWorthLiving{compiler};
return 0;
}
Will also be grateful for any hints to improve my code formatting, use of best practices, etc. cause I am new to the C++ and programming in general.
You need to call Vector whyMe(u);
if you want to use a regular constructor and not the initializer-list one. Initializing an object with {}
through regular constructors will only come into effect if your class does not provide an initializer-list constructor.
Take this example with the standard library's vector:
std::vector<int> v1(10); // vector of 10 elements with the default value 0
std::vector<int> v2{10}; // vector of 1 element with the value 10
The reason for the different behavior is that std::vector provides a constructor with initializer list and a constructor that takes size_t.
For more explanation with examples, see https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-list