簡體   English   中英

使用可轉換類型調用重載函數時模板化構造函數歧義

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM