简体   繁体   English

为什么这个构造函数没有给出不完整的类型错误?

[英]Why is this constructor not giving an incomplete type error?

I have two files test.h and main.cpp as shown below: 我有两个文件test.h和main.cpp,如下所示:

test.h test.h

#include <memory>

class TestImpl;

template <typename... T>
void createConnection(T&&... Args)
{
    // 1. Why is this working if the constructor is in cpp?
    std::unique_ptr<TestImpl> pimpl(new TestImpl(std::forward<T>(Args)...));
    std::cout << "Done..." << std::endl;

    // 2. Why is this not working if the constructor call has no issues?
    pimpl->sayHello();
}

main.cpp main.cpp中

#include <iostream>

#include "test.h"

class TestImpl
{
public:
    TestImpl(const std::string& first, const std::string& second)
        : _first(first)
        , _second(second)
    {
    }

    void sayHello()
    {
        std::cout << "Hello ... " << std::endl;
    }

private:
    std::string _first;
    std::string _second;
};

int main()
{
    std::cout << "Hello World!" << std::endl;
    createConnection("ABC", "DEF");
    return 0;
}

As evident from the comments my main question is why the constructor call is not giving an error "invalid use of incomplete type 'class TestImpl'...". 从评论中可以明显看出,我的主要问题是为什么构造函数调用没有给出错误“无效使用不完整类型'类TestImpl'......”。 For reference I am using GCC 5.2, with no specific flags. 作为参考,我使用的是GCC 5.2,没有特定的标志。

Simply put, GCC doesn't have to reject your program, and Clang doesn't have to accept it. 简而言之,GCC不必拒绝您的程序,而且Clang不必接受它。 It's ill-formed, no diagnostic required. 它形成不良,无需诊断。 Since TestImpl is incomplete, your template is in violation of 由于TestImpl不完整,因此您的模板违反了

[temp.res]/8 [temp.res] / 8

... The program is ill-formed, no diagnostic required, if: ......如果出现以下情况,该计划格式错误,无需诊断:

  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or 由于不依赖于模板参数的构造,或者在其定义之后立即对模板进行假设实例化将是不正确的,或者
  • the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template. 在假设实例中对这种构造的解释不同于在模板的任何实际实例中对相应构造的解释。

One could argue that the constructor being called is dependent, but the class name is surely not! 有人可能会争辩说被调用的构造函数是依赖的,但类名肯定不是!

In our case, a hypothetical instantiation with a pack of two strings immediately after the template definition will give different results than at the point of instantiation in your program. 在我们的例子中,在模板定义之后立即使用一个包两个字符串的假设实例化将给出与在程序中实例化时不同的结果。 This is because the class name itself (which is, again, not dependent) has different meaning in the two contexts. 这是因为类名本身(同样,不依赖)在两个上下文中具有不同的含义。

It's not a valid template definition. 它不是有效的模板定义。 But GCC is exercising some leeway here, since no diagnostic is required, and plowing on. 但海湾合作委员会正在这里行使一些余地,因为不需要进行诊断,而且需要继续进行。


This is succinctly summarized in the note under the bullets, which while not normative, describes your case: 这在子弹下的说明中简明扼要地概括,虽然不是规范性的,但描述了你的情况:

This can happen in situations including the following: 这种情况可能发生在包括以下情况:

  • a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is performed, or 非依赖名称中使用的类型在定义模板但在执行实例化时完成时不完整,或者

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM