使用stdargs对定义函数的未定义引用

时间:2012-09-29 23:26:34

标签: c++ templates g++

大家好日子。

我需要你用g ++技能来理解我发生的事情!

尝试链接时,g ++告诉我:

undefined reference to `bool Script::Call<bool>(asIScriptFunction*, std::string, ...)'

该功能在该文件中明确定义:

namespace Script
{
  template<typename RET>
  RET Call(asIScriptFunction* function, string fmt, ...)
  {
    asIScriptContext* context = Script::Engine::Get()->CreateContext();
    va_list ap;

    context->Prepare(function);
    va_start(ap, fmt);
    for (unsigned short i = 0 ; fmt[i] ; ++i)
    {
      if (i == 'O')
    context->SetArgObject(i, va_arg(ap, void*));
      else if (i == 'b')
    context->SetArgByte(i, va_arg(ap, int));
      else if (i == 'i')
    context->SetArgDWord(i, va_arg(ap, int));
      else if (i == 'f')
    context->SetArgFloat(i, va_arg(ap, double));
    }
    va_end(ap);
    context->Execute();

    RET to_ret = ScriptCallGetReturn<RET>(context);
    context->Release();
    return (to_ret);
  }
}

namespace Script
{
  template<> bool  Call<bool> (asIScriptFunction*, string fml, ...);
  template<> int   Call<int>  (asIScriptFunction*, string fml, ...);
  template<> float Call<float>(asIScriptFunction*, string fml, ...);
  template<> void* Call<void*>(asIScriptFunction*, string fml, ...);

  template<>
  void Call<void>(asIScriptFunction* function, string fmt, ...)
  {
    asIScriptContext* context = Script::Engine::Get()->CreateContext();
    va_list ap;

    context->Prepare(function);
    va_start(ap, fmt);
    for (unsigned short i = 0 ; fmt[i] ; ++i)
    {
      switch (fmt[i])
      {
    case '0':
      context->SetArgObject(i, va_arg(ap, void*));
      break ;
    case 'b':
      context->SetArgByte(i, va_arg(ap, int));
      break ;
    case 'i':
      context->SetArgDWord(i, va_arg(ap, int));
      break ;
    case 'f':
      context->SetArgFloat(i, va_arg(ap, double));
      break ;
      }
    }
    va_end(ap);
    context->Execute();
    context->Release();
  }
}

实际上,应该编译这些模板(它们实际上是在使用它们的同一文件中)。 这可能是什么原因发生的?可能是因为我使用了stdarg?

2 个答案:

答案 0 :(得分:4)

声明了该函数,但未在那里实现。链接器正在寻找实现。请注意,您提供的代码中只实现了Call<void>,但Call<bool>不是。

要使代码正确链接,您只需删除声明:

  template<> bool  Call<bool> (asIScriptFunction*, string fml, ...);
  template<> int   Call<int>  (asIScriptFunction*, string fml, ...);
  template<> float Call<float>(asIScriptFunction*, string fml, ...);
  template<> void* Call<void*>(asIScriptFunction*, string fml, ...);

答案 1 :(得分:2)

  

模板&LT;&GT; bool Call(asIScriptFunction *,string fml,...);

这不符合你的想法。这是使用template <typename RET> Call&lt; - RET声明bool的完整模板专精。你还没有定义它,那个旧的定义就出了门。功能模板专业化是一种奇怪的野兽,可能是最好的避免。

我认为,您要做的是告诉编译器您将使用Call的实例化。你不需要这样做。只需使用它。

bool variable_name = Call<bool> (some_script, other_args);