繁体   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