C++11 C++;带模板参数重载的11/14 friend运算符
在下面的代码中,我想为我要使用的特定类型定义实现二进制运算符链接的效果-对于普通运算符链接,二进制运算符返回相同类型的对象,大多数情况下只返回C++11 C++;带模板参数重载的11/14 friend运算符,c++11,templates,operator-overloading,c++14,overload-resolution,C++11,Templates,Operator Overloading,C++14,Overload Resolution,在下面的代码中,我想为我要使用的特定类型定义实现二进制运算符链接的效果-对于普通运算符链接,二进制运算符返回相同类型的对象,大多数情况下只返回*this,它可以很容易地再次用于链接同一类型的下一个对象 然而,在我的例子中,二进制运算符将两个相同类型对象(awaitable::ref)的两个reference_包装器作为输入,并返回一个类型为(awaitable post)的聚合对象,似乎很好地解释了这种情况,但在我的例子中,friend运算符有一个模板参数(这是避免递归模板实例化所必需的),这可
*this
,它可以很容易地再次用于链接同一类型的下一个对象
然而,在我的例子中,二进制运算符将两个相同类型对象(awaitable::ref
)的两个reference_包装器作为输入,并返回一个类型为(awaitable post)的聚合对象,似乎很好地解释了这种情况,但在我的例子中,friend运算符有一个模板参数(这是避免递归模板实例化所必需的),这可能会阻止编译器在实例化模板时生成正确的命名空间作用域函数。这就是您需要的吗
template < template <typename> class _awaitable, typename U >
friend auto operator||(_awaitable<std::reference_wrapper<U>> a1, ref a2)
{
awaitable<ref> r;
return r;
}
template
朋友自动操作员| |(_等待a1,参考a2)
{
等待者;
返回r;
}
EDIT1
我看到了你的答案,在那里你删除了模板参数以使其工作。如果void是你使用的唯一类型,那么这非常有效。如果你尝试使用另一种类型,它将失败。我必须解决的最接近的问题是使用std::ref(r1)来显式地使用它,例如
模板
friend waitiable operator | | |(std::reference_wrapper似乎带有模板模板参数的friend函数使模板推断失败。解决方案是删除模板模板参数,并将::ref用法扩展到friend函数定义中的std::reference_wrapper:
#include <functional>
template <typename T>
struct awaitable
{
typedef std::reference_wrapper<awaitable> ref;
// (A) - okay
friend awaitable<ref> operator||(ref a1, ref a2)
{
awaitable<ref> r;
return r;
}
// (XXX) - removing the template template parameter makes the template instantiation for a specific type T to generate a namespace version of the function!
friend awaitable<ref> operator||(std::reference_wrapper<awaitable<std::reference_wrapper<awaitable<T>>>> a1, ref a2)
{
awaitable<ref> r;
return r;
}
};
// template <typename T>
// awaitable<typename awaitable<T>::ref> operator||(typename awaitable<typename awaitable<T>::ref>::ref a1, typename awaitable<T>::ref a2)
// {
// awaitable<typename awaitable<T>::ref> r;
// return r;
// }
int main(int argc, const char * argv[])
{
awaitable<void> a1;
awaitable<void> a2;
auto r1 = a1 || a2; // Okay - r1 is of type awaitable<awaitable<void>::ref>
awaitable<void> a3;
auto r3 = r1 || a3; // now it works!
return 0;
}
#包括
模板
结构等待
{
typedef std::reference_wrapper很抱歉进行了编辑,我试图简化代码并尽可能消除任何可能的混淆,希望上面的代码应该非常易于阅读(根本没有向下滚动!)注意:输入对象都是reference|wrapper wrapper包装的,我特别不希望复制发生,在实际代码中,复制构造函数是deletedNo。在| waitiable之后缺少一个::ref,请参见:但这不是您正在或正在使用的,您正在调用r1 | a3->waitiable | waitiable我希望对象隐式转换为ref版本,第一个定义起作用,我想知道为什么XXX没有,我相信我们遇到了隐式模板重载解决问题,不太确定如何解决这正是(A)起作用的原因。但是(XXX)仍然不起作用:-(
template<typename U>
friend awaitable<ref> operator||(std::reference_wrapper<awaitable<std::reference_wrapper<awaitable<U>>>> a1, ref a2)
{
std::cout << "(XXX2)" << std::endl;
awaitable<ref> r;
return r;
}
awaitable<int> a4;
auto r4 = std::ref(r1) || a4;
#include <functional>
template <typename T>
struct awaitable
{
typedef std::reference_wrapper<awaitable> ref;
// (A) - okay
friend awaitable<ref> operator||(ref a1, ref a2)
{
awaitable<ref> r;
return r;
}
// (XXX) - removing the template template parameter makes the template instantiation for a specific type T to generate a namespace version of the function!
friend awaitable<ref> operator||(std::reference_wrapper<awaitable<std::reference_wrapper<awaitable<T>>>> a1, ref a2)
{
awaitable<ref> r;
return r;
}
};
// template <typename T>
// awaitable<typename awaitable<T>::ref> operator||(typename awaitable<typename awaitable<T>::ref>::ref a1, typename awaitable<T>::ref a2)
// {
// awaitable<typename awaitable<T>::ref> r;
// return r;
// }
int main(int argc, const char * argv[])
{
awaitable<void> a1;
awaitable<void> a2;
auto r1 = a1 || a2; // Okay - r1 is of type awaitable<awaitable<void>::ref>
awaitable<void> a3;
auto r3 = r1 || a3; // now it works!
return 0;
}