消除多個繼承類別成員的歧義
考慮以下可變參數基底範本:
<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
為什麼編譯器無法解決歧義:
成員查找[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中文網其他相關文章!