[英]Templated constructor ambiguity when calling overloaded function with castable type
我有2類, 都具有單參數模板的構造。 一個用作整數類型的catch all,在另一個類中用於綁定任何可迭代對象。 對於每種類型的特定函數,我有兩個重載。 如果我使用整數類型或字符串調用函數,或者至少對其中一個類調用的函數,我會收到有關調用歧義的錯誤。
#include <string>
class A {
public:
template <typename Iterable>
A(Iterable it) : s(it.begin(), it.end()) {}
private:
std::string s;
};
class B {
public:
template <typename Integer>
B(Integer i) : i(i + 1) {}
private:
int i;
};
void Use(A a)
{
// some thing
}
void Use(B b)
{
// some other thing
}
int main(void)
{
Use(0);
return 0;
}
編譯器似乎對多態性集合沒有足夠的了解,以確定實際上只有一種可能的解決方案。 這可能是因為模板在函數重載之前被“解析”了嗎? 我如何給編譯器一些幫助?
編譯器似乎對多態性集合沒有足夠的了解,以確定實際上只有一種可能的解決方案。
注意, 重載決策是根據功能模板的簽名執行的,包括函數名,函數參數,模板參數等; 但不是實現(例如函數體),在重載解析期間不會檢查。
您可以通過添加另一個具有默認值的模板參數來應用SFINAE來限制構造函數模板可以接受的類型。 例如
template <typename Iterable, typename = std::void_t<decltype(std::declval<Iterable>().begin()),
decltype(std::declval<Iterable>().end())>>
A(Iterable it) : s(it.begin(), it.end()) {}
和
template <typename Integer, typename = std::void_t<decltype(std::declval<Integer>() + 1)>>
B(Integer i) : i(i + 1) {}
在遵循SFINAE規則時,編譯器不會考慮該方法的實現。 換句話說,它會看到接受單個參數的類A constrator的聲明。
如果您希望SFINAE消除此選擇,則需要將未能替換的表達式移動到函數簽名中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.