gpt4 book ai didi

c++ - 解决 C++ 构造函数和调用歧义

转载 作者:搜寻专家 更新时间:2023-10-31 01:33:13 25 4
gpt4 key购买 nike

我有一个不错的小型万能 Array 类型,可以满足我目前的所有需求。

template <typename T>
class Array
{
...

public:
int Data; // custom value
virtual void InitData() { Data = 0; }

Array(const Array& array);
template <typename U, typename = std::enable_if<std::is_same<U, T>::value, U>> Array(const Array<U>& array);
template <typename... Ts> Array(const Ts&... items);

void Add(const T& item);
template <typename... Ts> void Add(const T& item, const Ts&... rest);
void Add(const Array& array);
}

template <typename... Ts> Array(const Ts&... items); 允许我执行 Array<T> array = { ... } ,并分配和返回 {...} 初始化列表。因为没有一个构造函数是显式的,所以非常方便,但这也是我现在卡住的原因。

我希望能够向数组中添加任何“合理”的内容。我现在的主要用例是:

using Curve = Array<float2>;

class Poly : public Array<float2> { using Array::Array; void InitData() override { Data = 1; } };
class Curve2 : public Array<float2> { using Array::Array; void InitData() override { Data = 2; } };
class Curve3 : public Array<float2> { using Array::Array; void InitData() override { Data = 3; } };

上面的 std::is_same<> 的东西是专门为了能够将所有曲线视为相同但不相同:不同程度的曲线类型,并且一切都是很好的“静态类型”,所以我在像 DrawCurve(const Curve&) 这样的函数中所做的一切是检查程度然后采取适当的行动。 Curve 是 Array 的一个很好的别名,Curve2 等是学位特化。它工作得很好。

当我开始构建曲线时,我通常有一个曲线对象,我向其添加点或曲线段。所以我希望能够做到:

Curve3 curve;
curve.Add(float2()); // ambiguity
curve.Add(Array<float2>());

不幸的是,当我调用 add 时我在这里遇到了歧义,因为 Add() 将采用 float2Array<float2> ,这工作正常,但 Array 具有隐式构造函数 template <typename... Ts> Array(const Ts&...) ,它可以将 float2 作为参数。所以歧义在

Array::Add(float2()); // and
Array::Add(Array<float2>(float2()));

我试过使构造函数显式接受数组,比如

template <typename A, typename = std::enable_if<std::is_same<A, Array>::value, A>>
void Add(const Array& array);

但后来我得到了从 Curve3 到 float2 等的新转换错误,它变得一团糟。

我希望在模板或其他 C++ 好东西的深处有一个简单的解决方案,这正是我所需要的。 (是的,我知道我可以重命名方法::AddItem() 和::AddArray() 问题将在一秒钟内解决,但我不想要这个,因为最终我想用 += 将所有这些加倍然后主要只是使用它。

有什么想法吗?

最佳答案

观察你想要的

 template <typename... Ts> Array(const Ts&... items);

仅当参数包包含至少一项且该项的类型不是Array 模板实例时才使用。如果参数包为空,这将成为默认构造函数,所以让我们单独处理这种情况。继续并显式定义一个默认构造函数,如果需要的话,让它做它需要做的事情;现在我们可以从这个用例中消除这种可能性,并继续前进。

在解决了这个问题之后,您在这里要做的是仅在具有一个参数时使用此构造函数:

 template <typename T1, typename... Ts> Array(const T1 &t1, const Ts&... items);

除了它使用的现有参数包之外,您还必须修改此构造函数以使用显式 t1。这应该足够简单,但这还不够。还是有歧义。只有当 T1 不是 Array 时,您才希望选择此构造函数。

可能有一种方法可以想出一些复杂的东西并将其填充到单个 std::enable_if 中,然后将其推送到此模板中。但为了清楚和简单起见,我会使用一个辅助类:

template<typename T> class is_not_array : public std::true_type {};

template<typename T>
class is_not_array<Array<T>> : public std::false_type {};

然后在这个构造函数的模板中添加一个简单的std::enable_if,仅当它的第一个模板参数不是Array时使用SFINAE选择这个构造函数,类似于您如何在另一个构造函数中使用 std::enable_if

这应该可以解决所有歧义。然后,在这个辅助类的帮助下,应该只使用至少一个不是 Array 的模板参数来选择这个构造函数。当它是一个 Array 时,这个构造函数将不可解析,这种情况将转到另一个构造函数。

我还建议在模板中使用通用引用,而不是 const T &

关于c++ - 解决 C++ 构造函数和调用歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41762099/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com