C++ 当转换运算符不明确时,在它们之间进行选择
我有两种类型:C++ 当转换运算符不明确时,在它们之间进行选择,c++,C++,我有两种类型: struct A { }; struct B { }; 我的函数取A或B: void fnA(A); // there are a lot of these functions void fnB(B); struct Foo { operator A(); operator B(); }; 我有一个类型,可以转换为a和B: void fnA(A); // there are a lot of these functions void fnB(B); str
struct A { };
struct B { };
我的函数取A
或B
:
void fnA(A); // there are a lot of these functions
void fnB(B);
struct Foo {
operator A();
operator B();
};
我有一个类型,可以转换为a
和B
:
void fnA(A); // there are a lot of these functions
void fnB(B);
struct Foo {
operator A();
operator B();
};
所以我可以调用fnA
和fnB
:
fnA(Foo()); // fine
fnB(Foo());
现在,我有一个重载函数:
void fn(A);
void fn(B);
我不能用Foo
来称呼他们,因为它不明确:
fn(Foo()); // ambiguous, which fn is called
在这种情况下,我想调用fn(A)
我可以添加第三个fn
重载:
inline void fn(Foo foo) {
fn(A(foo));
}
但我不喜欢这种方式,因为我有很多fn
函数,我不想大幅增加函数的数量(我有fn
-类函数分散在各地,这种改变会增加接口大小,这对我来说是不好的,因为我的接口已经很大了)
另一个解决方案(如果没有更好的选择,我会选择)是对Foo
使用继承:
struct Foo: A {
operator B();
};
在这种情况下,编译器将选择为fn(Foo())
调用fn(A)
,它不再是模棱两可的。但是我对这个解决方案不满意,因为Foo
并不是一个真正的A
,它是对继承的滥用(另一方面,它是一个比前一个更好的解决方案,因为它在本地解决了问题,我不必添加很多不需要的fn
函数)
还有别的办法解决这个问题吗
注意:我希望有一个不涉及显式转换的解决方案,我希望能够将
fnA(Foo())
、fnB(Foo())
、和fn(Foo())
转换为适当的类型:
#include <iostream>
#include <string>
struct A { };
struct B { };
struct Foo {
operator A() { return A{}; };
operator B() { return B{}; };
};
void fn(A) { std::cout << "A"; }
void fn(B) { std::cout << "B"; }
int main()
{
fn(static_cast<A>(Foo()));
}
#包括
#包括
结构A{};
结构B{};
结构Foo{
运算符A(){返回A{};};
运算符B(){返回B{};};
};
void fn(A){std::cout一个奇特的模板包装器怎么样:
void fn_impl(A);
void fn_impl(B);
template<typename x_AB = A, typename x_Foo = Foo>
void fn(x_Foo && foo)
{
return fn_impl(static_cast<x_AB>(foo));
}
fn(Foo()); // calls fn_impl(A);
fn<B>(Foo()); // calls fn_impl(B);
void fn_impl(A);
无效(B);
模板
无效fn(x_Foo&&Foo)
{
返回fn_impl(静态_cast(foo));
}
fn(Foo());//调用fn_impl(A);
fn(Foo());//调用fn_impl(B);
我认为通过使每个fn(B)
重载一个模板,您可以实现所需的行为:
void fn(A);
template<class = void>
void fn(B);
void bar()
{
fn(Foo());
fn(A());
fn(B());
}
void fn(A);
模板
无效fn(B);
空条()
{
fn(Foo());
fn(A());
fn(B());
}
这导致重载解析在考虑模板化函数之前选择fn(A)
。必要的工作相当于将template
放在每个B
重载之前(如果声明与定义分离,则将所有此类函数转换为模板专门化)
.“还有其他方法解决这个问题吗?”正确的方法是不要滥用隐式转换运算符。explicit关键字可能会有帮助。fn(static_cast(Foo());
只需显式告诉编译器要调用哪个重载运算符,例如:fn((A)Foo())
或者更好的fn(static_cast(Foo()))
@Jeka:不幸的是,关键是要进行隐式转换。@ArnavBorborah OP不希望这样做,因为他希望能够为其他方法隐式强制转换。@NathanOliver我已经切换了模板参数,所以现在它可以工作了。foo可能也是一个固定类型的参数。现在看起来不错。它还允许您执行fn({})
和fn({});
现在。有没有一种方法可以概括这一点(这样我就不必为我的fn
类函数创建模板函数)?我的意思是,代替这个解决方案,我可以很容易地使用我已经在我的答案中加入的内联函数。或者是有什么区别使得这个解决方案更好吗?请注意,如果发生这种情况,您还必须显式地使用fn(B{})
。这(尽管问题中没有说明)可能会发生,因为fn(B)
很可能不是为了好玩而写的。@MaxLanghof这些调用中的一个必须是明确的。很好,让我检查一下!(注意,我的问题不是工作量,而是函数的数量和接口大小。因此,如果你的解决方案可行,那么我完全可以-我的问题措辞不正确,我会编辑它)。