[英]ADL warning: ambiguous conversion with boost operators and SFINAE
[英]Selecting between conversion operators when they are ambiguous
我有兩種類型:
struct A { };
struct B { };
我有A
或B
功能:
void fnA(A); // there are a lot of these functions
void fnB(B);
我有一個類型,可以轉換為A
和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
like函數遍布各處,這種改變會增加接口大小,這對我不好,因為我的界面已經很大了)。
另一個解決方案(如果沒有給出更好的替代方案,我會選擇)是為Foo
使用繼承:
struct Foo: A {
operator B();
};
在這種情況下,編譯器將選擇為fn(Foo())
調用fn(A)
fn(Foo())
,它不再是模糊的。 但是我對這個解決方案並不滿意,因為Foo
不是真正的A
,它是對繼承的誤用(另一方面,它是一個比前一個更好的解決方案,因為它解決了本地問題,我不知道必須添加許多不需要的fn
函數)。
有沒有其他方法可以解決這個問題?
注意:我想要一個不涉及顯式轉換的解決方案,我希望能夠編寫fnA(Foo())
, fnB(Foo())
和fn(Foo())
。
一個花哨的模板包裝器怎么樣:
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);
我認為你可以通過使每個fn(B)
重載一個模板來實現所需的行為:
void fn(A);
template<class = void>
void fn(B);
void bar()
{
fn(Foo());
fn(A());
fn(B());
}
這會導致重載fn(A)
在考慮模板化函數之前選擇fn(A)
。 必要的工作相當於在每個函數的每個B
重載之前放置template<class = void>
(如果聲明與定義分開,則將所有這些函數轉換為模板特化)。
演示 。
只需將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()));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.