首頁  >  文章  >  後端開發  >  為什麼在 C 中呼叫可變參數模板成員函數時會出現多重繼承歧義?

為什麼在 C 中呼叫可變參數模板成員函數時會出現多重繼承歧義?

Susan Sarandon
Susan Sarandon原創
2024-10-25 01:50:30830瀏覽

Why Does Multiple Inheritance Ambiguity Occur in C   When Calling a Variadic Template Member Function?

消除多個繼承類別成員的歧義

考慮以下可變參數基底範本:

<code class="cpp">template <typename... Types>
class Base {
public:
    template <typename T>
    typename std::enable_if<Contains<T, Types...>::value>::type
    foo() { std::cout << "Base::foo()\n"; }
};

考慮以下可變參數基底範本:

<code class="cpp">struct Derived : public Base<int, char>, public Base<double, void> {};</code>

foo()只能使用與類型包中的類型之一相符的模板參數來呼叫成員。現在,讓我們定義一個具有不重疊基底類型的衍生類別:

呼叫 Derived().foo() 應該直觀地解析為 Base 。基類。然而,編譯器抱怨歧義。

為什麼編譯器無法解決歧義:

成員查找[class.member.lookup] 的合併規則指出,當派生類別具有空聲明集(無成員) ,必須合併所有基底類別的查找集。在我們的例子中,基類具有不同的聲明集,因此合併失敗。

解決方案:

<code class="cpp">struct Derived : public Base<int, char>, public Base<double, void> {
    using Base<int, char>::foo;
    using Base<double, void>::foo;
};</code>

為了避免這種歧義,我們可以向派生類別添加using 聲明class:

透過在派生類中引入foo 的重載,我們有效地繞過了合併規則。

使用收集器類別:

<code class="cpp">template <typename... Bases>
struct BaseCollector;

template <typename Base, typename... Bases>
struct BaseCollector<Base, Bases...> : Base, BaseCollector<Bases...> {
    using Base::foo;
    using BaseCollector<Bases...>::foo;
};

struct Derived : BaseCollector<Base2<int>, Base2<std::string>> {};</code>

或者,我們可以使用模板類別來聚合所有基底類別的using 聲明:

這種方法在C 17 中編譯效率更高,因為它允許對using 聲明進行套件擴展。

以上是為什麼在 C 中呼叫可變參數模板成員函數時會出現多重繼承歧義?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn