gpt4 book ai didi

c++ - 可变参数模板的链接器错误

转载 作者:太空狗 更新时间:2023-10-29 20:39:40 24 4
gpt4 key购买 nike

我有一个带有可变参数模板和辅助函数的程序:

#include <iostream>
#include <string>

using std::cout;

template<typename... Ts>
void fooImpl(char const *cp, Ts... args);

template<typename... Ts>
inline void foo(const std::string &s, Ts... args)
{
fooImpl(s.c_str(), args...);
}

void fooImpl(char const *cp)
{
// do something
}

template<typename T, typename... Ts>
void fooImpl(char const *cp, T val, Ts... args)
{
char special{'@'};

while (*cp)
{
if (*cp == special)
{
// handle val ...

// recurse over remaining args
fooImpl(cp, args...);
return;
}
++cp;
}
}

int main()
{
std::string s = "Hello!";
foo("Text", s, "C++", 3.14159, 42);
}

这给出了一个链接器错误:

/tmp/ccZpPMC2.o:vt-test.cc: function void foo<std::string, char const*, double, int>(std::string const&, std::string, char const*, double, int): error:
undefined reference to 'void fooImpl<std::string, char const*, double, int>(char const*, std::string, char const*, double, int)'

如果我放入 foo 的定义,编译和链接都很好在main()之前下来.所以我认为这只是一个错误,但我通过 GCC 4.9 和 clang 3.5 得到了这个,所以也许我遗漏了什么?

最佳答案

template<typename T, typename... Ts>
void fooImpl(char const *cp, T val, Ts... args) { /* ... */ }

您正在声明原始模板的重载 (!)。

通话以来

fooImpl(s.c_str(), args...);

参数列表中有一个pack-expansion,unqualified-id表示一个从属名1。从属名称解析适用。 [temp.dep.candidate]:

For a function call that depends on a template parameter, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2, 3.4.3) except that:

  • For the part of the lookup using unqualified name lookup (3.4.1) [..] only function declarations from the template definition context are found.

  • For the part of the lookup using associated namespaces (3.4.2), only function declarations found in either the template definition context or the template instantiation context are found.

可以肯定地说,非限定名称查找不会找到第二个重载,因为它只考虑来自模板定义上下文的声明。

ADL 确实适用于此,但全局命名空间不会与参数包中的任何类型相关联。我们有 std::string, char const*, double, int。 [basic.lookup.argdep]/2 指定:

  • If T is a fundamental type, its associated sets of namespaces and classes are both empty.

  • If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the namespaces of which its associated classes are members. Furthermore, if T is a class template specialization, its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces of which any template template arguments are members; and the classes of which any member templates used as template template arguments are members.

因此,基本类型和 std::string 都没有将全局命名空间作为关联的命名空间包含在内。

长话短说...

...在 ADL 期间未搜索全局命名空间,并且未找到第二个重载。因此,函数模板的第一个重载是唯一找到并随后由重载决策选择的重载。虽然未定义第一个重载,因此会发出链接器错误。


1) [temp.dep]/1:

In an expression of the form:

      postfix-expression ( expression-listopt )

where the postfix-expression is an id-expression, the id-expression denotes a dependent name if

  • any of the expressions in the expression-list is a pack expansion (14.5.3),
  • [..]

关于c++ - 可变参数模板的链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27067433/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com