简体   繁体   English

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

[英]C++ ADL of a function in another namespace

I have a function template printSize calling the overloaded function getSize before getSize is declared. 我有一个函数模板printSize调用重载函数getSize之前getSize声明。 For a clearer structure of my program, I would like to put both functions in different namespaces A and B , as the commented code lines show. 为了使程序结构更清晰,我希望将两个函数放在不同的命名空间AB ,如注释的代码行所示。 However, ADL will then fail to find getSize . 但是,ADL随后将找不到getSize

Actually, printSize and getSize are implemented in different header files. 实际上, printSizegetSize是在不同的头文件中实现的。 Therefore, I cannot put a using namespace directive. 因此,我不能放置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;
}

Is there a way to make this code compile with printSize and getSize being defined in different namespaces? 有没有一种方法可以使此代码与在不同名称空间中定义的printSizegetSize一起编译?

One solution would be to put the tag into the B namespace, and pull it into A . 一种解决方案是将标记放入B名称空间,然后将其拉入A

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

namespace A {
   using B::tag;
}

Now, because tag comes from the B namespace, it will associate B for ADL. 现在,因为tag来自B名称空间,所以它将B与ADL关联。

You can use a using declaration to introduce a name from another namespace. 您可以使用using声明从另一个名称空间引入名称。 For example: 例如:

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 depends on a template parameter T , so ADL will be used in the second phase of lookup (when this template is instantiated) to find other getSize s provided by the user. getSize取决于模板参数T ,因此在查找的第二阶段(实例化此模板时)将使用ADL查找用户提供的其他getSize Here B::getSize should be declared before printSize and tag itself seems to be redundant. 这里B::getSize应该在printSizetag本身似乎是多余的之前声明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM