另一个命名空间中函数的 C++ ADL
C++ ADL of a function in another namespace
我有一个函数模板 printSize
在声明 getSize
之前调用重载函数 getSize
。为了让我的程序结构更清晰,我想将两个函数放在不同的命名空间 A
和 B
中,如注释代码行所示。但是,ADL 将无法找到 getSize
.
其实printSize
和getSize
是在不同的头文件中实现的。因此,我不能放置 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;
}
有没有办法让这段代码在 printSize
和 getSize
被定义在不同命名空间的情况下编译?
您可以使用 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
提供的其他 getSize
用户。这里 B::getSize
应该在 printSize
之前声明并且 tag
本身似乎是多余的。
一个解决方案是将标签放入 B
命名空间,然后将其拉入 A
.
namespace B {
template <typename T> struct tag {};
}
namespace A {
using B::tag;
}
现在,因为 tag
来自 B
命名空间,它将关联 B
用于 ADL。
我有一个函数模板 printSize
在声明 getSize
之前调用重载函数 getSize
。为了让我的程序结构更清晰,我想将两个函数放在不同的命名空间 A
和 B
中,如注释代码行所示。但是,ADL 将无法找到 getSize
.
其实printSize
和getSize
是在不同的头文件中实现的。因此,我不能放置 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;
}
有没有办法让这段代码在 printSize
和 getSize
被定义在不同命名空间的情况下编译?
您可以使用 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
提供的其他 getSize
用户。这里 B::getSize
应该在 printSize
之前声明并且 tag
本身似乎是多余的。
一个解决方案是将标签放入 B
命名空间,然后将其拉入 A
.
namespace B {
template <typename T> struct tag {};
}
namespace A {
using B::tag;
}
现在,因为 tag
来自 B
命名空间,它将关联 B
用于 ADL。