簡體   English   中英

C ++朋友函數模板重載和SFINAE在clang ++,g ++,vc ++中的不同行為(C ++ 14模式)

[英]C++ friend function template overloading and SFINAE different behaviors in clang++, g++, vc++ (C++14 mode)

因此,以下代碼在clang ++(3.8.0)下構建並運行成功,但在g ++(6.3.0)和vc ++(19.10.24903.0)下都失敗了。 g ++和vc ++都抱怨重新定義operator &&。

有誰知道哪個編譯器有問題。 對於無法編譯代碼的編譯器,編譯錯誤的解決方法是什么?

#include <functional>
#include <iostream>

template <typename T>
struct awaitable
{
    friend awaitable<void> operator&&(awaitable a1, awaitable a2)
    {
        std::cout << "operator&&(awaitable a1, awaitable a2) - T: " << typeid(T).name() << std::endl;
        return awaitable<void>{};
    }

    template <typename U = T, typename std::enable_if<!std::is_same<U, void>::value>::type* = nullptr>
    friend awaitable<void> operator&&(awaitable<void> a1, awaitable<U> a2)
    {
        std::cout << "operator&&(awaitable<void> a1, awaitable<U> a2) - U: " << typeid(T).name() << std::endl;
        return awaitable<void>{};
    }

    template <typename U = T, typename std::enable_if<!std::is_same<U, void>::value>::type* = nullptr>
    friend awaitable<void> operator&&(awaitable<U> a1, awaitable<void> a2)
    {
        std::cout << "operator&&(awaitable<U> a1, awaitable<void> a2) - U: " << typeid(T).name() << std::endl;
        return awaitable<void>{};
    }
};

int main(int argc, const char * argv[])
{
    awaitable<int> a1, a2, a3, a4;
    auto ar = a1 && (a1 && a2) && (a2 && a3) && a4;
}

clang ++: http//coliru.stacked-crooked.com/a/cb01926bbcacdfb0

g ++: http//coliru.stacked-crooked.com/a/73d17a5ae26f22eb

vc ++: http//webcompiler.cloudapp.net/

SFINAE在模板實例化級別工作,即在struct awaitable<T> ,而不是在模板的單個成員級別。 awaitable<void>是一個有效的實例化,因此它實例化了該類的所有3個成員的聲明,復制了后者2。

並不是兩個定義相互沖突 - 每個定義都與自身沖突( 例子 )( 更多細節 )。

解決方法1

定義類外的幫助程序操作符(已授予,與您擁有的不完全相同 - 這些將成為模板的任何實例的朋友)

#include <functional>
#include <iostream>

template <typename T>
struct awaitable
{
    friend awaitable<void> operator&&(awaitable a1, awaitable a2)
    {
        std::cout << "operator&&(awaitable a1, awaitable a2) - T: " << typeid(T).name() << std::endl;
        return {};
    }

    template<typename U>
    friend std::enable_if_t<!std::is_void<U>::value, awaitable<void>> operator&&(awaitable<void> a1, awaitable<U> a2);

    template<typename U>
    friend std::enable_if_t<!std::is_void<U>::value, awaitable<void>> operator&&(awaitable<U> a1, awaitable<void> a2);

};

template<typename U>
std::enable_if_t<!std::is_void<U>::value, awaitable<void>> operator&&(awaitable<void> a1, awaitable<U> a2)
{
    std::cout << "operator&&(awaitable<void> a1, awaitable<U> a2) - U: " << typeid(U).name() << std::endl;
    return {};
}

template<typename U>
std::enable_if_t<!std::is_void<U>::value, awaitable<void>> operator&&(awaitable<U> a1, awaitable<void> a2)
{
    std::cout << "operator&&(awaitable<U> a1, awaitable<void> a2) - U: " << typeid(U).name() << std::endl;
    return {};
}

int main(int argc, const char * argv[])
{
    awaitable<int> a1, a2, a3, a4;
    auto ar = a1 && (a1 && a2) && (a2 && a3) && a4;
}

解決方法2

使用無SFINAE可言,而是一個專業化awaitable 請注意,專業化是相反的 - 基礎實現是awaitable<void>的特殊情況,專門化是針對其他一切的。

#include <functional>
#include <iostream>

template <typename T, bool isvoid = std::is_void<T>::value>
struct awaitable
{
    friend awaitable<void> operator&&(awaitable a1, awaitable a2)
    {
        std::cout << "operator&&(awaitable a1, awaitable a2) - void" << std::endl;
        return {};
    }
};

template <typename T>
struct awaitable<T, false>
{
    friend awaitable<void> operator&&(awaitable a1, awaitable a2)
    {
        std::cout << "operator&&(awaitable a1, awaitable a2) - T: " << typeid(T).name() << std::endl;
        return {};
    }

    friend awaitable<void> operator&&(awaitable<void> a1, awaitable<T> a2)
    {
        std::cout << "operator&&(awaitable<void> a1, awaitable<T> a2) - U: " << typeid(T).name() << std::endl;
        return {};
    }

    friend awaitable<void> operator&&(awaitable<T> a1, awaitable<void> a2)
    {
        std::cout << "operator&&(awaitable<T> a1, awaitable<void> a2) - void" << std::endl;
        return {};
    }
};

int main(int argc, const char * argv[])
{
    awaitable<int> a1, a2, a3, a4;
    auto ar = a1 && (a1 && a2) && (a2 && a3) && a4;
}

暫無
暫無

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

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