Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 未编译函数模板中使用的类的正向声明_C++_Templates_Gcc_Forward Declaration - Fatal编程技术网

C++ 未编译函数模板中使用的类的正向声明

C++ 未编译函数模板中使用的类的正向声明,c++,templates,gcc,forward-declaration,C++,Templates,Gcc,Forward Declaration,下面的代码不是用gcc编译的,而是用MSVC编译的 class B; class A { B *_parent; public: template <typename T> void Do(T val) { _parent->DoB(val); } A(B *parent) : _parent(parent) { } }; class B : public A { pu

下面的代码不是用gcc编译的,而是用MSVC编译的

class B;

class A
{
    B *_parent;

public:

    template <typename T>
    void Do(T val)
    {
        _parent->DoB(val);
    }

    A(B *parent)
        :   _parent(parent)
    {
    }
};

class B : public A
{
public:

    B()
        : A(nullptr)
    {
    }

    void DoB(int val)
    {
        cout << val << endl;
    }
};

int main() {
    B b;
    A a(&b);
    a.Do(10);
    return 0;
}
根据类似帖子,根据本标准第14.6.9段,gcc的行为是正确的。但这是违反直觉的,因为模板应该只在使用的地方实例化。唯一的用法是在定义了所有类之后


我的问题是这个问题的解决办法是什么?因为在这种情况下使用成员模板非常方便。可能是架构或其他方面的问题?

您可以声明依赖于
B
A
部分是已知的,但稍后再定义它们。声明如下所示

class B;

class A
{
    B *_parent;

    public:
        template <typename T> void Do(T val); /* (see below) */
        A(B *parent) :   _parent(parent) {}
};
最后定义缺失的部分

template <typename T> void A::Do(T val)
{
    _parent->DoB(val); /* Fine, B is known. */
}
模板无效A::Do(T val)
{
_父->DoB(val);/*很好,B是已知的*/
}

作为补充说明,使用gcc 8编译的原始代码仅包含一个警告。

您可以添加额外的层:

class A
{
    B *_parent;

private:
    template <typename TB, typename T>
    static void CallDoB(TB* b, T&& val) {
        b->DoB(std::forward<T>(val));
    }
public:

    template <typename T>
    void Do(T val)
    {
        CallDoB(_parent, val);
    }

    A(B *parent) : _parent(parent) {}
};
A类
{
B*父母;
私人:
模板
静态无效CallDoB(TB*b、T和val){
b->DoB(标准:正向(val));
}
公众:
模板
无效Do(T val)
{
CallDoB(_parent,val);
}
A(B*家长):_家长(家长){}
};

现在
b->
依赖于模板,并被推迟到真正的实例化。

设计肯定很奇怪。也许你会想使用?14.6.9的什么版本的标准?在任何情况下,是的,模板定义中任何不“依赖”模板参数的内容都必须在模板定义中格式良好,即使从未实例化,这里的
\u parent->DoB
子表达式违反了该规则。在本例中,我修复了标题中的术语,因为,实际上,我已经提出了一个类似的解决方案:
template void Do(T val){static_cast(this)->\u parent->DoB(val);}
template <typename T> void A::Do(T val)
{
    _parent->DoB(val); /* Fine, B is known. */
}
class A
{
    B *_parent;

private:
    template <typename TB, typename T>
    static void CallDoB(TB* b, T&& val) {
        b->DoB(std::forward<T>(val));
    }
public:

    template <typename T>
    void Do(T val)
    {
        CallDoB(_parent, val);
    }

    A(B *parent) : _parent(parent) {}
};