jjzjj

c++ - 同级友元运算符似乎不参与重载决议

coder 2024-02-11 原文

在编写使类能够根据模板参数为 operator+ 提供重载的 CRTP 模板时,我发现类内友元运算符似乎不参与重载决议,如果没有的话arguments 是它在其中定义的类的类型。

归结:

enum class FooValueT{
    zero, one, two
};

class Foo{
    FooValueT val_;
public:
    Foo(FooValueT x) : val_(x){};

    Foo& operator+=(Foo other){
        val_ = (FooValueT)((int)val_ + (int)other.val_);
        return *this;
    }

    //overload for Foo+Foo, FooValueT+Foo and Foo+FooValueT
    friend Foo operator+(Foo lhs, Foo rhs){
        Foo ret = lhs;
        return ret += lhs;
    }

    //explicit overload for FooValueT+FooValueT
    friend Foo operator+(FooValueT lhs, FooValueT rhs){
        return (Foo)lhs + (Foo)rhs;
    }
};

看起来有点过分,但这是必要的,因为 Foo my = FooValueT::one + FooValueT::zero; 应该是一个有效的表达式,如果没有参数具有类类型,则它们是未隐式转换,如 this answer 中所述回答我之前的一个问题。

尽管付出了所有这些努力,以下代码仍无法编译:

int main(int argc, char* argv[])
{
    Foo my = FooValueT::zero;
    my += FooValueT::one;
    my = Foo(FooValueT::zero) + FooValueT::two;
    my = FooValueT::zero + Foo(FooValueT::two);
    my = FooValueT::zero + FooValueT::two; //error C2676
    return 0;
}

错误信息是:

error C2676: binary '+' : 'FooValueT' does not define this operator or a conversion to a type acceptable to the predefined operator

一旦我将运算符完全移出类,或者将其声明为友元但在类外定义,此问题就会解决。当 Foo 是要从中派生的模板类时,两者似乎都不是可行的选择。

据我所知,上述 operator+(ValueT,ValueT) 的类内友元定义应该创建一个自由函数,就像这个定义一样:

class Foo{
/*All the stuff you saw previously*/
    friend Foo operator+(FooValueT lhs, FooValueT rhs);
};

Foo operator+(FooValueT lhs, FooValueT rhs){
    return (Foo)lhs + (Foo)rhs;
}

我哪里错了?与普通的自由友元函数相比,函数的类内友元定义是否改变了重载决策规则?

最佳答案

n3376 11.3/6-7

A function can be defined in a friend declaration of a class if and only if the class is a non-local class (9.8), the function name is unqualified, and the function has namespace scope.

Such a function is implicitly inline. A friend function defined in a class is in the (lexical) scope of the class in which it is defined. A friend function defined outside the class is not (3.4.1).

在您的情况下,运算符在类范围内,当您尝试调用此运算符时,ADL 不会尝试在类中查找运算符,因为两个参数都没有此类的类型。只需编写自由函数(或声明不在类里面的 friend )。

似乎你不能这样做,在类中声明友元函数的问题是函数将在类范围内,但你不能将此函数声明为自由友元函数,因为编译器无法推断返回类型参数.

关于c++ - 同级友元运算符似乎不参与重载决议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27376365/

有关c++ - 同级友元运算符似乎不参与重载决议的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  3. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  4. ruby-on-rails - 在 heroku 的 .fonts 文件夹中包含自定义字体,似乎无法识别它们 - 2

    Heroku支持人员告诉我,为了在我的Web应用程序中使用自定义字体(未安装在系统中,您可以在bash控制台中使用fc-list查看已安装的字体)我必须部署一个包含所有字体的.fonts文件夹里面的字体。问题是我不知道该怎么做。我的意思是,我不知道文件名是否必须遵循heroku的任何特殊模式,或者我必须在我的代码中做一些事情来考虑这种字体,或者如果我将它包含在文件夹中它是自动的......事实是,我尝试以不同的方式更改字体的文件名,但根本没有使用该字体。为了提供更多详细信息,我们使用字体的过程是将PDF转换为图像,更具体地说,使用rghostgem。并且最终图像根本不使用自定义字体。在

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. ruby - 带括号和 splat 运算符的并行赋值 - 2

    我明白了:x,(y,z)=1,*[2,3]x#=>1y#=>2z#=>nil我想知道为什么z的值为nil。 最佳答案 x,(y,z)=1,*[2,3]右侧的splat*是内联扩展的,所以它等同于:x,(y,z)=1,2,3左边带括号的列表被视为嵌套赋值,所以它等价于:x=1y,z=23被丢弃,而z被分配给nil。 关于ruby-带括号和splat运算符的并行赋值,我们在StackOverflow上找到一个类似的问题: https://stackoverflow

  7. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  8. ruby-on-rails - "rails generate rspec:install"似乎失败了 - 2

    运行:ruby1.9.3p0和Rails3.2.1尝试使用rspec但当我尝试将其安装到我的应用程序中时出现以下错误:/Users/Si/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.1/lib/rails/railtie/configuration.rb:85:in`method_missing':undefinedmethod`generators'for#(NoMethodError)from/Users/Si/.rvm/gems/ruby-1.9.3-p0/gems/rspec-rails-2.0.0.beta.18/lib/rspec-r

  9. ruby - 定义自定义 Ruby 运算符 - 2

    问题是:除了在“OperatorExpressions”?例如:1%!2 最佳答案 是的,可以创建自定义运算符,但有一些注意事项。Ruby本身并不直接支持它,但是superatorsgem做了一个巧妙的把戏,将运算符链接在一起。这允许您创建自己的运算符,但有一些限制:$geminstallsuperators19然后:require'superators19'classArraysuperator"%~"do|operand|"#{self}percent-tilde#{operand}"endendputs[1]%~[2]#Out

  10. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

随机推荐