вариационные шаблоны и списки инициализаторов сужают различия - PullRequest
0 голосов
/ 05 февраля 2019

Так что это не имеет никакого смысла.

С этим классом:

template< typename T, int nDimensions = 2 >
class Vec {
private:
std::array< T, nDimensions > elements_;

public:
typedef T ValueType;

Vec() : elements_() {}

template <typename... U>
Vec(U... ts) : elements_{ ts... } {}

Vec(const std::initializer_list<T>& values){
    std::copy(values.begin(), values.end(), elements_.begin());
}

template <typename T2, int nDimension2>
Vec(Vec<T2, nDimension2> const& copy){
    for (int i = 0; i < nDimensions; i++){
        this->elements_[i] = (T)static_cast<T2>(copy[i]);
    }
}
};

Почему это прекрасно делать:

Vec<int,2> twoi = { 1, 2.1 }; //An int and a double

Но не:

Vec<int,2> twoi2(1,2.1); //conversion from 'double' to 'int' requires a narrowing conversion

Это просто не кажется интуитивным.Для списка Initializer он просто выполняет преобразование, а с другой стороны, когда шаблон расширяется, он должен просто передать значение типа double, которое преобразуется в int.

Это то, что функция должна быть расширенатоже если я прав:

std::array< int, 2> elements_ = { 1.2,1};

Какой компилируется просто отлично.

Есть ли способ изменить этот конструктор, чтобы игнорировать преобразования?

Обновление Visual Studios 20153 сборка:

1>------ Build started: Project: MathTests, Configuration: Debug Win32 ------
1>  Source.cpp
1>d:\projects\stevenstuff\mathtests\source.cpp(12): warning C4838: conversion from 'double' to 'int' requires a narrowing conversion
1>d:\projects\stevenstuff\mathtests\source.cpp(12): warning C4244: 'initializing': conversion from 'double' to 'int', possible loss of data
1>d:\projects\stevenstuff\util\vec\include\vec.h(19): error C2397: conversion from 'const double' to 'int' requires a narrowing conversion
1>  d:\projects\stevenstuff\mathtests\source.cpp(10): note: see reference to function template instantiation 'Vec<int,2>::Vec<double,int>(const double &,const int &)' being compiled

1 Ответ

0 голосов
/ 06 февраля 2019

Понял, в конце концов.

Простой ответ: есть преобразование, которое должно произойти.Некоторые компиляторы справляются с этим и просто приводятся напрямую, некоторые - нет, и жалуются, что это невозможно.Обойти это можно, вставив подлый бросок в конструктор.

template <typename... U>
    Vec(const U&... ts) 
        : elements_{(T)(ts)... } {
    }

Тогда все расширяется как: элементы _ ((T) ts [1] ... ext.

...