【问题标题】:Why is this ADL resolution ambigous为什么这个 ADL 分辨率不明确
【发布时间】:2016-12-11 15:14:59
【问题描述】:

我正在尝试使用 c++ asio 库 (http://think-async.com/Asio/asio-1.10.6/doc/asio/overview/core/allocation.html) 的自定义分配器功能。我的函数代码都在命名空间bb 中,自定义分配函数void* asio_handler_allocate(std::size_t size, ...) 也是如此。我希望 ADL 选择我的自定义版本,但由于某种原因它会导致模棱两可:

c:\mysrv\asio\detail\handler_alloc_helpers.hpp(38): error C2668: 'bb::asio_handler_allocate': ambiguous call to overloaded function
1>  c:\mysrv\connection.hpp(16): note: could be 'void *bb::asio_handler_allocate(std::size_t,...)' [found using argument-dependent lookup]
1>  c:\mysrv\asio\impl\handler_alloc_hook.ipp(27): note: or       'void *asio::asio_handler_allocate(std::size_t,...)'
1>  c:\mysrv\asio\detail\handler_alloc_helpers.hpp(38): note: while trying to match the argument list '(std::size_t, bb::Server::do_accept::<lambda_18e060fa7342c1167c1b66e6dfdfd1b2> *)'

任何关于为什么第二个也匹配和/或如何正确使用此功能的解释将不胜感激

谢谢

附:我正在添加 boost-asio 标记,因为它应该是同一个库,但只在不同的命名空间中。我实际上使用的是在这里找到的独立 c++11 版本http://think-async.com/

这是一个简化的例子:

#include "asio.hpp"
#include <memory>
#include <iostream>

namespace bb {
    void* asio_handler_allocate(std::size_t size, ...) {
        std::cerr << 'H' << ' ' << /**h <<*/ ' ' << size << '\n';
        return asio::asio_handler_allocate(size);
    }

    class Connection
        : public std::enable_shared_from_this<Connection>
    {
    public:
        Connection(asio::ip::tcp::socket socket)
            : socket_(std::move(socket))
        {
        }

        void start()
        {
            do_read();
        }

    private:
        void do_read()
        {
            auto self(shared_from_this());
            socket_.async_read_some(asio::buffer(data_),
                [this, self](std::error_code ec, std::size_t length)
            {
                if (!ec)
                {
                    do_write(length);
                }
            });
        }

        void do_write(std::size_t length)
        {
            auto self(shared_from_this());
            asio::async_write(socket_, asio::buffer(data_, length),
                [this, self](std::error_code ec, std::size_t /*length*/)
            {
                if (!ec)
                {
                    do_read();
                }
            });
        }

        asio::ip::tcp::socket socket_;
        std::array<char, 1024> data_;
    };

    class Server
    {
    public:
        Server(asio::io_service& io_service, short port)
            : acceptor_(io_service, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port)),
            socket_(io_service)
        {
            do_accept();
        }

    private:
        void do_accept()
        {
            acceptor_.async_accept(socket_,
                [this](std::error_code ec)
            {
                if (!ec)
                {
                    std::make_shared<Connection>(std::move(socket_))->start();
                }

                do_accept();
            });
        }

        asio::ip::tcp::acceptor acceptor_;
        asio::ip::tcp::socket socket_;
    };
}

int main(int argc, char* argv[])
{
    try
    {
        if (argc != 2)
        {
            std::cerr << "Usage: server <port>\n";
            return 1;
        }

        asio::io_service io_service;
        bb::Server s(io_service, std::atoi(argv[1]));
        io_service.run();
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}

【问题讨论】:

  • 反对者,请解释
  • edit您的问题提供minimal reproducible example
  • 我不知道,但我猜,这是因为签名是asio_handler_allocate(size_t, ...),而不是像asio_handler_allocate(size_t, std::function) 这样的具体类型。
  • 默认版本使用...,因为在重载解析中一切都优于...。除了... 之外的所有内容。

标签: c++ c++11 boost-asio


【解决方案1】:

ADL 只是将参数的命名空间添加到应查找名称的命名空间列表中(这不是很精确,但就您的问题而言,这就足够了)。它不会自动使该命名空间中的重载成为首选。如果找到两个排名相同的匹配项,仍然会发生模棱两可的情况。在您的情况下,两者完全相同。

如果你阅读了你链接的ASIO文档,你就会知道声明ADL重载的正确方法是

 void* asio_handler_allocate(size_t, Handler);

其中Handler 是用户定义的处理程序类型。上面的声明也可以有Handler 的可能的CV 限定符。在这种情况下,找到的两个重载是一个带有第二个参数的具体类型,另一个带有...。任何与类型参数匹配的合法 的排名都高于可变参数(不要与 C++11 可变模板参数混淆)。因此,不会有模棱两可的匹配

【讨论】:

  • 我原以为通过 ADL 找到的那个优先级更高。感谢您澄清这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-18
  • 2010-10-17
  • 2019-11-18
  • 2015-10-22
  • 1970-01-01
相关资源
最近更新 更多