![](/img/trans.png)
[英]Print an address of function in C++, g++/clang++ vs vc++ , who is right?
[英]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.