簡體   English   中英

構造函數模板可以在類模板的c ++ 17參數推導中導致歧義

[英]Can constructor template cause ambiguity in the c++17 parameter deduction of class template

考慮一個簡單的例子:

template <class T>
struct foo {
    template <template <class> class TT>
    foo(TT<T>&&) {}
    foo(foo<T>&&){}
    foo() {}
};

int main() {
    foo      f1(foo<int>{}); //case 1.
    foo<int> f2(foo<int>{}); //case 2.
}

情況1.在clang中的foo類的模板參數推導中導致模糊,但在gcc中沒有。 我認為模板函數(這里 - 構造函數)在重載決策中具有較低的優先級。 這不是這種情況嗎?

錯誤信息:

prog.cc:10:14: error: ambiguous deduction for template arguments of 'foo'
    foo      f1(foo<int>{}); //case 1.
             ^
prog.cc:4:5: note: candidate function [with T = int, TT = foo]
    foo(TT<T>&&) {}
    ^
prog.cc:5:5: note: candidate function [with T = int]
    foo(foo<T>&&){}
    ^
1 error generated.

[鏗鏘演示] [gcc演示]

這是一個Clang錯誤。 候選集由c'tors組成的事實應該是無關緊要的,因為在形成候選集之后,使用相同的規則來選擇最佳重載以用於排序隱式轉換序列和模板函數排序。

引用[over.match.funcs] / 1

[over.match.funcs]的子條款描述了在使用重載決策的七個上下文中的每個上下文中提交給重載決策的候選函數集和參數列表。 這些子條款中定義的源轉換和構造僅用於描述重載解析過程。 使用這種轉換和構造不需要實現。

這清楚地表明過載解決過程始終是相同的。 唯一的區別是候選集的形成方式。

並由[over.match.class.deduct] / 1指定

形成一組功能和功能模板,包括:

  • 對於template-name指定的主類模板的每個構造函數,如果定義了模板,則具有以下屬性的函數模板:

    • 模板參數是類模板的模板參數,后跟構造函數的模板參數(包括默認模板參數)(如果有)。

    • 函數參數的類型是構造函數的類型。

    • 返回類型是由模板名稱和模板參數指定的類模板特化,其對應於從類模板獲得的模板參數。

每個c'tor將偽函數引入候選集。 像這樣:

template <class T>                           foo(foo<T>&&) -> foo<T> 
template <class T, template<class> class TT> foo(TT<T>&&) -> foo<T> 

為了進一步說明,如果這是一個免費功能bar

template <template <class> class TT, class T>
void bar(TT<T>&&) {}

template <class T>
void bar(foo<T>&&){}

然后模板函數排序會使第一個過載低於第二個過載。

它們沒有較低的優先級。 您可以使用SFINEA解決問題。 這在Scott Meyers的Effective Modern C ++中有所描述。

template <class T>
struct foo {
    template <template <class> class TT, class =  std::enable_if_t<!std::is_same_v<foo<T>, std::decay_t<TT<T>>>>>
    foo(TT<T>&&) {}
    foo(foo<T>&&){}
    foo() {}
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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