C++在强制转换操作符和可变参数构造函数之间混淆

Avi*_*Avi 7 c++ typecast-operator variadic-templates c++11

C++(更具体地说,MinGW的g ++实现)变得混乱.我有一个数学Vector类,它包含任意数量的任意类型的元素.元素类型和元素数在编译时指定.

Vector类在其中一个构造函数和我称之为"resize"运算符之间变得混乱.调整大小运算符允许程序员将一个大小的向量转换为另一个任意大小的向量.如果投射向量具有比基本向量更多的元素,则用1填充.这是实施:

/*
 * 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;
}
Run Code Online (Sandbox Code Playgroud)

vector类还有一个类型安全的可变参数构造函数,可以接受任意数量的元素组合(必须是T类型)和任意数量的Vectors(可以包含任意数量的元素,并且必须是T类型),所以只要添加到提供的向量中的元素数量的裸元素的数量等于构造向量包含的元素的数量.

因此这是有效的:

vec3 foo(vec2(1, 2), 3);
Run Code Online (Sandbox Code Playgroud)

但不是这个.

vec3 bar(vec4(1, 2, 3, 4), 5);
Run Code Online (Sandbox Code Playgroud)

我确保在编译时通过使用计数器递归它们来提供适当数量的元素,然后我使用静态断言来确保计数器以向量可以包含的元素数量结束.这通常很好,除了以下代码:

vec4 bar(1, 2, 3, 4);
(vec3) bar; //PROBLEM HERE
Run Code Online (Sandbox Code Playgroud)

发生的事情是C++认为(vec3)bar要求可变参数构造函数,实际上它应该调用resize运算符.我试过让它们明确,但它没有奏效.当我有上面的代码而不是可变参数构造函数时,如何确保C++使用resize运算符?

简而言之,我如何告诉C++使用它:

//resize operator
template<typename T, unsigned int N, unsigned int rN>
Vector<T, N>::operator Vector<T, rN>();
Run Code Online (Sandbox Code Playgroud)

而不是这个:

//constructor
template<typename T, unsigned int N, typename ... Args>
Vector<T, N>::Vector(Args ... arguments);
Run Code Online (Sandbox Code Playgroud)

当我有这个代码时:

(vec3) someVec4;
Run Code Online (Sandbox Code Playgroud)

如果不清楚,vec3和vec4定义如下:

typedef Vector<float, 3> vec3;
typedef Vector<float, 4> vec4;
Run Code Online (Sandbox Code Playgroud)

编辑:

新闻,大家好!即使我使用static_cast(someVec4),它仍然使用vec4参数调用vec3构造函数.我不知道为什么.

另一个编辑:

使构造函数显式允许隐式强制转换工作,但不允许隐式转换.也就是说这段代码有效:

vec3 foo = someVec4;
Run Code Online (Sandbox Code Playgroud)

但是这段代码仍然给我一个静态的断言失败:

vec3 foo = static_cast<vec3>(someVec4);
Run Code Online (Sandbox Code Playgroud)

这基本上没有意义,因为我声明了可变参数构造函数是显式的,因此不应该在那里调用它.

此外,根据要求,这是一个SSCCE

TL; DR版本是我的代码在我尝试显式调用类型转换操作符时调用显式构造函数,但是当我尝试隐式调用它时却没有.

cel*_*chk 1

我认为最简单的方法是让代码正常工作,用转换构造函数替换转换运算符。由于该构造函数比可变参数构造函数更专业,因此它应该始终优先。