我写了一些代码S s; ... s = {};,希望它最终与S s = {};相同。但是事实并非如此。下面的示例重现该问题:

#include <iostream>

struct S
{
    S(): a(5) { }
    S(int t): a(t) {}

    S &operator=(int t)  { a = t; return *this; }
    S &operator=(S const &t) = default;

    int a;
};

int main()
{
    S s = {};

    S t;
    t = {};

    std::cout << s.a << '\n';
    std::cout << t.a << '\n';
}

输出为:
5
0

我的问题是:
  • 为什么在这里选择operator=(int),而不是“歧义”或另一个?
  • 是否有一个整洁的解决方法,而无需更改S

  • 我的意图是s = S{};。如果可行,编写s = {};会很方便。我目前正在使用s = decltype(s){};,但我希望避免重复输入类型或变量名。

    最佳答案


    {}int是身份转换([over.ics.list]/9)。 {}S是用户定义的转换([over.ics.list]/6)(从技术上讲,它是{}const S&的转换,先经过[over.ics.list]/8和[over.ics.ref],然后再返回[over.ics。列表]/6)。

    第一场胜利。



    技巧std::experimental::optional拉动的一种变体使t = {}始终使t为空。
    关键是使operator=(int)为模板。如果您只想接受intint,那么它将变为

    template<class Int, std::enable_if_t<std::is_same<Int, int>{}, int> = 0>
    S& operator=(Int t) { a = t; return *this; }
    

    如果要启用转换,可以使用不同的约束(在这种情况下,您可能还希望通过引用接受参数)。

    关键是,通过将正确的操作数的类型设为模板参数,可以阻止t = {}使用此重载-因为{}是非推论上下文。


    template<class T> T default_constructed_instance_of(const T&) { return {}; }s = default_constructed_instance_of(s);是否计数?

    关于c++ - 重载分辨率: assignment of empty braces,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33511641/

    10-11 19:40