簡體   English   中英

為什么 MSVC 和 Clang 為相同的 function 模板調用產生不同的輸出?

[英]Why do MSVC and Clang produce different outputs for the same function template call?

在弄亂了概念之后,我在 Visual Studio 中遇到了一些我不理解的東西,盡管我不知道這里的問題是否與特定的概念有關。 我敢肯定這種行為是有原因的,但如果有人能解釋一下,那就太好了。 這個問題有兩個部分。 對於以下代碼段:

#include <concepts>
#include <utility>

template <typename PolicyType, typename T, typename... Ts>
concept concept_policy = requires(Ts&&... args) 
{
    { PolicyType::template Create<T>(args...) } -> std::same_as<T*>;
};

struct basic_policy
{
    template <typename T, typename... Ts>
    static T* Create(Ts&&... args)
    {
        return new T { std::forward<Ts>(args)... };
    }
};

struct type_a
{
    int m_val;
};

template <concept_policy<int> TPolicy = basic_policy>
static void DoSomething()
{
    //works on msvc, msvc needs the "template" for no args, but not with?
    {
        type_a* type1 = TPolicy::Create<type_a>(5); //why is this fine without template?
        type_a* type2 = TPolicy::template Create<type_a>(); //why does this require template if the above doesn't?
    }

    // //clang requires both to have "template"
    // {
    //     type_a* type1 = TPolicy::template Create<type_a>(5);
    //     type_a* type2 = TPolicy::template Create<type_a>();
    // }
}

int main()
{

    DoSomething();

    {
        //both versions compile fine without "template"
        basic_policy policy;
        type_a* type1 = basic_policy::Create<type_a>(5);
        type_a* type2 = basic_policy::Create<type_a>(); 
    }

    return 0;
}
  1. 為什么 msvc 和 clang 在這里產生不同的輸出? Msvc 可以省略使用 arguments 調用的“模板”,但並非沒有
  2. 使用類似的策略設計,有沒有辦法在 Create 前加上“模板”? 理想情況下,我希望能夠調用TPolicy::Create<type>(...);

Clang 是正確的:對TPolicy::Create<type_a>的調用需要單詞template ,因為TPolicy是依賴類型。

具體來說,根據標准,當我們有T::m<形式的片段時,其中T是當前實例化之外的依賴類型,編譯器必須假定<是小於運算符,而不是模板的開頭參數列表。 如果您的意思是<作為模板參數列表,那么您必須在m前面加上關鍵字template

此行為在[temp.names]/3中指定。 不滿足任何所列條件的<必須被解釋為表示小於運算符; 編譯器無法使用上下文信息來確定它是否意味着模板參數列表的開頭。

至於為什么 MSVC 有時無法診斷出違規,我不確定。

沒有辦法使TPolicy::Create<type>(...); 只需在沒有template關鍵字的情況下工作。 如果你真的討厭寫template ,你必須重組你的代碼,讓Create是一個非成員,有點像標准庫中的std::get (必須以.template get<i>()的形式調用如果它是 class 成員)。 我猜在這種情況下, Create可能是一個 class 模板,它將策略 class 作為其模板 arguments 之一,而您要創建的類型是另一個。 有人告訴我,出於這個確切原因,人們經常將他們的模板設為非成員(以避免編寫template )。 我認為這是一個很大的錯誤。 最好寫template而不是選擇不太自然的設計。

暫無
暫無

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

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