【问题标题】:Template variadic compile error on calling default constructor调用默认构造函数时模板可变参数编译错误
【发布时间】:2019-07-31 06:12:59
【问题描述】:

关于调用模板可变参数方法的模板方法,我有一个奇怪的行为,我找不到问题所在。我正在使用 Visual Studio Community 2017。

编译错误出现在以下方法中:

// AScene.hpp
#include "Scriptable.hpp"

template <typename T>
void AScene::initialize_(void) {
    std::shared_ptr<AGameObject> root = std::make_shared<T>();

    // ...
    root->addComponent<Scriptable>(3); // it works (3 is just a random value to bypass the default constructor, see below the Scriptable struct definition)
    root->addComponent<Scriptable>(); // error C2760 unexpected token ')', expected 'expression'
    // ...
}

如果我尝试在此方法中使用默认构造函数,则会出现上面提到的编译错误。 这个方法在派生类中被调用,这里:

// MyScene.cpp
#include "AScene.hpp"

void MyScene::initialize(void) {
    AScene::initialize_<Level>();
    // If I call root->addComponent<Scriptable>() directly here, its working perfectly
}

这里是addComponent模板可变参数方法的实现:

// AGameObject.hpp
template <typename C, typename ...Args>
void AGameObject::addComponent(Args&& ... args) {
    entity_.assign<C>(std::forward<Args>(args) ...);
}

我无法向您展示 assign() 代码,因为它是库的一部分,但是当我不在 initialize_ 中调用它时,此代码始终有效。

这是我的 Scriptable 类:

// Scriptable.hpp
struct Scriptable {
    Scriptable(void) = default;
    Scriptable(int i) {} // remember, used to bypass the default constructor
    // ...
};

实际上,当我在模板方法initialize_中调用addComponent方法时,编译器似乎只是忽略/找不到默认构造函数。你知道我做错了什么吗?

如果您需要更多信息,请告诉我。

编辑:

我刚刚检查了库中的 assign() 实现,构造函数是这样调用的:

C(std::forward<Args>(args) ...);

如果你想查看,这里是链接:https://github.com/alecthomas/entityx/blob/master/entityx/Entity.h#L648

这正是编译器告诉我的:

1>AGameObject.cpp 1>path\ascene.hpp(89): error C2760: syntax error: unexpected token ')', expected 'expression' 1>path\ascene.hpp(89): note: This diagnostic occurred in the compiler generated function 'void AScene::initialize_(void)'

【问题讨论】:

  • 在您未显示的部分编译错误中可能有一些更相关的信息。您发布的代码看起来不错,但不知道 assign 做了什么,您怎么能期望这里有任何帮助?就您显示的代码而言,没有调用 Scriptable 的构造函数。
  • 你试过用Scriptable() = default代替Scriptable(void) = default吗?
  • @max66 是的,我已经尝试过了,@super 我已经编辑了关于 assign 做什么的问题。
  • 我认为你应该阅读这个stackoverflow.com/questions/29879564/…
  • AScene.hpp 缺少#include "AGameObject.hpp"Here 是一个 mcve。线索是编译器不知道addComponent 是一个模板,所以它看到((root-&gt;addComponent) &lt; Scriptable) &gt; ()(即&lt;&gt; 是小于和大于运算符)。

标签: c++ templates variadic entityx


【解决方案1】:

看到这个问题没有答案,我很惊讶。我遇到了同样的问题,我发现这是可行的:

    root->addComponent<Scriptable>(3); // it works (3 is just a random value to bypass the default constructor, see below the Scriptable struct definition)
    root->addComponent<Scriptable>(); // error C2760 unexpected token ')', expected 'expression'
    root->template addComponent<Scriptable>(); //it works too

PS 这是我很久以前才学会做的那些怪癖之一,但我并没有真正理解为什么需要它。这里解释了它背后的理论:Calling template function within template class 但是话又说回来,我不明白为什么使用编译好的参数调用。所以如果有人能详细说明,我将不胜感激。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-01
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多