C++另一个命名空间中函数的 ADL

C++ ADL of a function in another namespace

本文关键字:ADL 函数 另一个 命名空间 C++      更新时间:2023-10-16

我有一个函数模板printSize在声明getSize之前调用重载函数getSize。为了使我的程序结构更清晰,我想将这两个函数放在不同的命名空间中AB,如注释的代码行所示。但是,ADL 将无法找到getSize

实际上,printSizegetSize在不同的头文件中实现。因此,我不能提出using namespace指令。

#include <array>
#include <iostream>
#include <string>
namespace A {
template <typename T> struct tag {};
template <typename T>
void printSize(const T &data)
{
size_t data_size = getSize(data, tag<T>{});
//size_t data_size = B::getSize(data, tag<T>{});
std::cout << "Size: " << data_size << std::endl;
}
//} // namespace A
//namespace B {
constexpr size_t getSize(const int &, tag<int>)
{
return sizeof(int);
}
size_t getSize(const std::string &str, tag<std::string>)
{
return str.size();
}
template <typename T, size_t N>
size_t getSize(const std::array<T, N> &array, tag<std::array<T, N>>)
{
size_t array_size = 0;
for (const T &element : array)
array_size += getSize(element, tag<T>{});
return array_size;
}
} // namespace A/B
int main()
{
int a;
A::printSize(a);
std::array<std::string, 2> arr = {{"foo", "foobar"}};
A::printSize(arr);
return 0;
}

有没有办法使此代码编译,并在不同的命名空间中定义printSizegetSize

一种解决方案是将标签放入B命名空间中,然后将其拉入A中。

namespace B {
template <typename T> struct tag {};
}
namespace A {
using B::tag;
}

现在,由于tag来自B命名空间,因此它将关联 ADL 的B

可以使用using声明从另一个命名空间引入名称。例如:

template <typename T>
void printSize(const T &data)
{
using B::getSize;
std::size_t data_size = getSize(data, tag<T>{});
std::cout << "Size: " << data_size << std::endl;
}

getSize取决于模板参数T,因此 ADL 将在查找的第二阶段(当此模板实例化时)用于查找用户提供的其他getSize。在这里,B::getSize应该在printSize之前声明,tag本身似乎是多余的。