0

我想让一个结构用转发参数初始化它的成员。除非我声明析构函数以及尝试从函数返回结构(我认为这需要复制构造函数),否则它可以编译并正常工作。

#include <utility>

struct Foo 
{
  int val;

  Foo(int val) : val(val)
  {
  }
};

struct FooContainer
{
    Foo member;

    template<typename... Args>
    FooContainer(Args&&... args) : 
      member(std::forward<Args>(args)...)
    {}

    ~FooContainer() {}
};

FooContainer getFooContainer()
{
  FooContainer retval(0);
  return retval;
}

int main() {}

编译器错误是:

example.cc: In constructor ‘FooContainer::FooContainer(Args&& ...) [with Args = FooContainer&]’:
example.cc:27:   instantiated from here
example.cc:18: error: no matching function for call to ‘Foo::Foo(FooContainer&)’
example.cc:7: note: candidates are: Foo::Foo(int)
example.cc:4: note:                 Foo::Foo(const Foo&)

看起来它正在尝试为它生成一个复制构造函数FooContainer但失败了,因为它没有办法初始化 Foo。然而,如果我删除FooContainer构造函数或析构函数,它编译得很好。*为什么要这样做?

*无论如何,在http://cpp.sh/上使用 GCC 4.9.2。即使未声明析构函数,Ubuntu 上的 g++ 4.4.3 也会出现相同的错误。

4

1 回答 1

1

我不能确切地告诉您为什么会发生这种情况(标准专家将能够),但问题实际上是由于您定义了用户定义的析构函数而引起的。

删除它,问题就消失了(无论如何您都想使用零规则,对吗?)

如果您必须拥有析构函数并且由于某种原因无法重构它,那么替换移动构造函数(您通过提供析构函数隐式删除)也将解决它。

解决方案 1 - 使用 0 规则:

#include <utility>

struct Foo
{
    int val;

    Foo(int val) : val(val)
    {
    }
};

struct FooContainer
{
    Foo member;

    template<typename... Args>
    FooContainer(Args&&... args) :
    member(std::forward<Args>(args)...)
    {}

//    ~FooContainer() {}
};

FooContainer getFooContainer()
{
    FooContainer retval(0);
    return retval;
}

int main() {}

解决方案 2 - 使用规则 5:

#include <utility>

struct Foo
{
    int val;

    Foo(int val) : val(val)
    {
    }
};

struct FooContainer
{
    Foo member;

    template<typename... Args>
    FooContainer(Args&&... args) :
    member(std::forward<Args>(args)...)
    {}

    FooContainer(const FooContainer&) = default;
    FooContainer(FooContainer&&) = default;
    FooContainer& operator=(const FooContainer&) = default;
    FooContainer& operator=(FooContainer&&) = default;

    ~FooContainer() {}
};

FooContainer getFooContainer()
{
    FooContainer retval(0);
    return retval;
}

int main() {}
于 2016-04-04T00:21:23.717 回答