我有一个令人难以置信的令人兴奋的库,它可以翻译点:它可以与任何点类型一起使用
template<class T>
auto translate_point(T &p, int x, int y) -> decltype(p.x, p.y, void())
{
p.x += x;
p.y += y;
}
template<class T>
auto translate_point(T &p, int x, int y) -> decltype(p[0], void())
{
p[0] += x;
p[1] += y;
}
translate_point
将与具有publicx
和y
member的点一起使用,并且还将x
与y
分别由第一个元素和第二个元素表示的元组/可索引容器一起工作。
问题是,另一个库使用publicx
和定义了一个点类y
,但是还允许建立索引:
struct StupidPoint
{
int x, y;
int operator[](int i) const
{
if(i == 0) return x;
else if(i == 1) return y;
else throw "you're terrible";
}
};
使用两个库的我的应用程序如下:
int main(int argc, char **argv)
{
StupidPoint stupid { 8, 3 };
translate_point(stupid, 5, 2);
return EXIT_SUCCESS;
}
但这使GCC(和叮当声)感到不满:
error: call of overloaded ‘translate_point(StupidPoint&, int, int)’ is ambiguous
现在,我知道了为什么会发生这种情况,但是我想知道如何解决此问题(假设我无法更改StupidPoint的内部结构),并且,如果没有简单的解决方法,作为库实现者,我将如何使这一过程变得更容易处理。
如果要优先考虑使用public x
/的情况y
,则可以执行以下操作:
template<class T>
auto translate_point_impl(int, T &p, int x, int y) -> decltype(p.x, p.y, void())
{
p.x += x;
p.y += y;
}
template<class T>
auto translate_point_impl(char, T &p, int x, int y) -> decltype(p[0], void())
{
p[0] += x;
p[1] += y;
}
template<class T>
void translate_point(T &p, int x, int y) {
translate_point_impl(0, p, x, y);
}
不用说,相反的配置是通过切换第一个参数的类型给出的。
如果您具有三个或更多选项(例如N
),则可以使用基于模板的技巧。
这是上面切换到这种结构后的示例:
template<std::size_t N>
struct choice: choice<N-1> {};
template<>
struct choice<0> {};
template<class T>
auto translate_point_impl(choice<1>, T &p, int x, int y) -> decltype(p.x, p.y, void()) {
p.x += x; p.y += y;
}
template<class T>
auto translate_point_impl(choice<0>, T &p, int x, int y) -> decltype(p[0], void()) {
p[0] += x;
p[1] += y;
}
template<class T>
void translate_point(T &p, int x, int y) {
// use choice<N> as first argument
translate_point_impl(choice<1>{}, p, x, y);
}
如您所见,现在N
可以采用任何值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句