С++ (точнее, реализация g++ в MinGW) запутывается. У меня есть математический класс Vector, который содержит произвольное количество элементов произвольного типа. Тип элемента и количество элементов указываются во время компиляции.
Класс Vector путается между одним из своих конструкторов и тем, что я назвал оператором «изменения размера». Оператор изменения размера позволяет программисту преобразовать вектор одного размера в вектор другого произвольного размера. Если вектор приведения содержит больше элементов, чем базовый вектор, он дополняется единицами. Вот реализация:
/*
* resize operator:
* T is the type of element the base vector holds
* N is the number of elements the base vector holds
* rN is the size of the new vector
*/
template<typename T, unsigned int N, unsigned int rN>
operator Vector<T, rN>() const
{
Vector<T, rN> resize;
for (unsigned int i = 0; i < rN; i++)
{
resize[i] = i < N ? this->elements[i] : 1;
}
return resize;
}
Класс vector также имеет типобезопасный вариативный конструктор, который может принимать любое количество любых комбинаций элементов (которые должны быть типа T) и любое количество векторов (которые могут содержать любое количество элементов и должны быть типа T), поэтому пока количество голых элементов, добавленных к количеству элементов в предоставленных векторах, равно количеству элементов, содержащихся в конструирующем векторе.
Таким образом, это будет действительным:
vec3 foo(vec2(1, 2), 3);
но не это.
vec3 bar(vec4(1, 2, 3, 4), 5);
Я гарантирую, что правильное количество элементов было предоставлено во время компиляции, рекурсивно просматривая их все со счетчиком, затем я использую статическое утверждение, чтобы убедиться, что счетчик заканчивается на количестве элементов, которое может содержать вектор. Обычно это работает хорошо, за исключением следующего кода:
vec4 bar(1, 2, 3, 4);
(vec3) bar; //PROBLEM HERE
Происходит то, что C++ думает, что (vec3) bar запрашивает вариативный конструктор, хотя на самом деле он должен вызывать оператор изменения размера. Я пытался сделать их явными, но это не сработало. Как убедиться, что C++ использует оператор изменения размера, когда у меня есть приведенный выше код, а не вариативный конструктор?
Короче говоря, как мне сказать С++ использовать это:
//resize operator
template<typename T, unsigned int N, unsigned int rN>
Vector<T, N>::operator Vector<T, rN>();
вместо этого:
//constructor
template<typename T, unsigned int N, typename ... Args>
Vector<T, N>::Vector(Args ... arguments);
когда у меня есть этот код:
(vec3) someVec4;
Если это неясно, vec3 и vec4 определены как таковые:
typedef Vector<float, 3> vec3;
typedef Vector<float, 4> vec4;
ИЗМЕНИТЬ:
Новости, всем! Даже когда я использую static_cast(someVec4), он по-прежнему вызывает конструктор vec3 с аргументом vec4. Я не знаю почему.
ДРУГОЕ РЕДАКТИРОВАНИЕ:
Создание явного конструктора позволяет работать неявным приведениям, но не явным. То есть этот код работает:
vec3 foo = someVec4;
Но этот код по-прежнему дает мне ошибку статического утверждения:
vec3 foo = static_cast<vec3>(someVec4);
Что в принципе не имеет смысла, потому что я объявил вариативный конструктор явным, и поэтому его не следует вызывать там.
Кроме того, по запросу вы можете получить SSCCE.
Версия TL; DR заключается в том, что мой код вызывает явный конструктор, когда я пытаюсь явно вызвать оператор приведения типов, но не когда я пытаюсь вызвать его неявно.
explicit
? - person aschepler   schedule 11.08.2012