gpt4 book ai didi

使用命名空间时,C++ 模板函数无法使用 g++ 进行编译

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:14:26 25 4
gpt4 key购买 nike

下面的代码编译得很好:(没有命名空间)

#include <vector>

template <class T>
void foo(const int & from, std::vector<T> & to)
{
for (int i = 0; i < 5; i++)
{
T bar;
foo(from, bar);
to.push_back(bar);
}
}

struct Bar
{
int a;
int b;
};

struct Baz
{
std::vector<Bar> bars;
};


void foo(const int & from, Bar & to)
{
to.a = from;
to.b = from - 1;
}

void foo(const int & from, Baz & to)
{
foo(from, to.bars);
}

void fooTest()
{
int num = 10;
Baz baz;
foo(num, baz);
}

int main()
{
fooTest();
}

但是当我为 Bar 和 Baz 引入命名空间时,它无法编译。 (带命名空间)

#include <vector>

template <class T>
void foo(const int & from, std::vector<T> & to)
{
for (int i = 0; i < 5; i++)
{
T bar;
foo(from, bar);
to.push_back(bar);
}
}

// When I add this namespace, it fails to compile
namespace BarBar
{
struct Bar
{
int a;
int b;
};

struct Baz
{
std::vector<Bar> bars;
};
}


void foo(const int & from, BarBar::Bar & to)
{
to.a = from;
to.b = from - 1;
}

void foo(const int & from, BarBar::Baz & to)
{
foo(from, to.bars);
}

void fooTest()
{
int num = 10;
BarBar::Baz baz;
foo(num, baz);
}

int main()
{
fooTest();
}

显示错误:

with_namespace.cpp: In instantiation of ‘void foo(const int&, std::vector<T>&) [with T = BarBar::Bar]’:
with_namespace.cpp:37:22: required from here
with_namespace.cpp:9:12: error: no matching function for call to ‘foo(const int&, BarBar::Bar&)’
foo(from, bar);
^
with_namespace.cpp:4:6: note: candidate: template<class T> void foo(const int&, std::vector<T>&)
void foo(const int & from, std::vector<T> & to)
^
with_namespace.cpp:4:6: note: template argument deduction/substitution failed:
with_namespace.cpp:9:12: note: ‘BarBar::Bar’ is not derived from ‘std::vector<T>’
foo(from, bar);
^

另请注意,使用 MSVC 时,带有命名空间的代码编译得很好。为什么编译器在使用命名空间时找不到定义?

我使用的是以下版本:g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

更新:在 @M.M 指出函数查找如何用于模板和 ADL 之后,我进行了以下修复:

#include <vector>



template <class T>
void foo(const int & from, std::vector<T> & to)
{
for (int i = 0; i < 5; i++)
{
T bar;
foo(from, bar);
to.push_back(bar);
}
}

namespace BarBar
{
struct Bar
{
int a;
int b;
};

struct Baz
{
std::vector<Bar> bars;
};
};


// Put them in the same namespace as Bar so that the templated foo find this function
namespace BarBar
{
using ::foo; // We are going to use templated foo in the latter functions

void foo(const int & from, BarBar::Bar & to)
{
to.a = from;
to.b = from - 1;
}

void foo(const int & from, BarBar::Baz & to)
{
foo(from, to.bars);
}

}

void fooTest()
{
int num = 10;
BarBar::Baz baz;
BarBar::foo(num, baz);
}



int main()
{
fooTest();
}

最佳答案

在代码中:

template <class T>
void foo(const int & from, std::vector<T> & to)
{
T bar;
foo(from, bar);

名称bar类型相关的,因为它的类型取决于模板参数。此外,名称 foo(在 foo(from, bar) 中)是一个依赖名称,因为其中一个函数调用参数是类型依赖的。 (C++17 [temp.dep]/1)。

相关名称的名称查找工作方式如下 (C++17 [temp.dep.res]/1):

In resolving dependent names, names from the following sources are considered:

  • Declarations that are visible at the point of definition of the template.
  • Declarations from namespaces associated with the types of the function arguments both from the instantiation context and from the definition context

第二个要点称为 ADL(参数相关查找)。


在您的第二个代码中,查找相关的 foo 什么也找不到:

  • 在模板点没有其他可见的定义
  • intT 的相关命名空间(即BarBar::Bar)是:BarBar,并且没有名称 BarBar::foo

在第一段代码中,查找依赖的foo:int::Bar关联的命名空间是:全局命名空间。全局命名空间中有::foo,所以它可以被ADL找到。

要修复第二个代码,您应该将带有 BarBar:: 参数的 foo 的后续定义移动到 namespace BarBar 中. (在这种情况下,您还需要在第 37 行使用 using::foo 来查找模板 foo)。

关于使用命名空间时,C++ 模板函数无法使用 g++ 进行编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50672619/

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