2012-11-21 76 views
3

我目前正在尝试用boost :: asio编写一些代码,并使用clang 3.1进行编译。“候选模板被忽略:替换失败:”编译器错误?

我有一个简单的函数对象:

struct tcp_socket_match_condition 
{ 
    template <typename TIter> 
    std::pair<TIter, bool> operator()(TIter begin, TIter end) const 
    { 
     auto result(std::find(begin, end, '\n')); 
     const bool found(result != end); 
     return std::make_pair(found ? ++result : end, found); 
    } 
}; 

我尝试将此传递到boost::asio::read_until功能,像这样:产生

boost::asio::read_until(socket, stream, match_condition_, error); 

编译器错误看起来指出的是,它不能找到正确的功能过载。任何想法为什么这不起作用?

我提供了完整的类和编译器错误。

In file included from src/network/admin_socket.cpp:1: 
In file included from include/bytes42/arthur/network/admin_socket.hpp:4: 
include/bytes42/arthur/network/tcp_socket.hpp:95:21: error: no matching function for call to 'read_until' 
        boost::asio::read_until(socket, stream, match_condition_, error); 
        ^~~~~~~~~~~~~~~~~~~~~~~ 
src/network/admin_socket.cpp:81:10: note: in instantiation of member function 
     'bytes42::arthur::network::tcp_socket<bytes42::arthur::network::detail::tcp_socket_match_condition>::listen' requested here 
     socket_.listen(); 
       ^
/usr/local/include/boost/asio/impl/read_until.hpp:47:13: note: candidate function [with SyncReadStream = 
     boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, Allocator = 
     std::__1::allocator<char>] not viable: no known conversion from 'bytes42::arthur::network::detail::tcp_socket_match_condition' to 'char' for 3rd 
     argument; 
std::size_t read_until(SyncReadStream& s, 
      ^
/usr/local/include/boost/asio/impl/read_until.hpp:138:13: note: candidate function [with SyncReadStream = 
     boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, Allocator = 
     std::__1::allocator<char>] not viable: no known conversion from 'bytes42::arthur::network::detail::tcp_socket_match_condition' to 
     'const std::string' (aka 'const basic_string<char, char_traits<char>, allocator<char> >') for 3rd argument; 
std::size_t read_until(SyncReadStream& s, 
      ^
/usr/local/include/boost/asio/impl/read_until.hpp:203:13: note: candidate function [with SyncReadStream = 
     boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, Allocator = 
     std::__1::allocator<char>] not viable: no known conversion from 'bytes42::arthur::network::detail::tcp_socket_match_condition' to 
     'const boost::regex' (aka 'const basic_regex<char, regex_traits<char> >') for 3rd argument; 
std::size_t read_until(SyncReadStream& s, 
      ^
/usr/local/include/boost/asio/impl/read_until.hpp:260:13: note: candidate template ignored: substitution failure [with SyncReadStream = 
     boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, Allocator = 
     std::__1::allocator<char>, MatchCondition = bytes42::arthur::network::detail::tcp_socket_match_condition] 
std::size_t read_until(SyncReadStream& s, 
      ^
/usr/local/include/boost/asio/impl/read_until.hpp:312:20: note: candidate template ignored: substitution failure [with SyncReadStream = 
     boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, Allocator = 
     std::__1::allocator<char>, MatchCondition = bytes42::arthur::network::detail::tcp_socket_match_condition] 
inline std::size_t read_until(SyncReadStream& s, 
       ^
/usr/local/include/boost/asio/impl/read_until.hpp:37:20: note: candidate function template not viable: requires 3 arguments, but 4 were provided 
inline std::size_t read_until(SyncReadStream& s, 
       ^
/usr/local/include/boost/asio/impl/read_until.hpp:93:20: note: candidate function template not viable: requires 3 arguments, but 4 were provided 
inline std::size_t read_until(SyncReadStream& s, 
       ^
/usr/local/include/boost/asio/impl/read_until.hpp:193:20: note: candidate function template not viable: requires 3 arguments, but 4 were provided 
inline std::size_t read_until(SyncReadStream& s, 
       ^
1 error generated. 
make: *** [build/src/network/admin_socket.o] Error 1 

类:

template <typename TMatchCondition> 
    class tcp_socket 
    { 
     public: 
      typedef std::function<std::string(const std::string&)> data_callback; 

     public: 
      tcp_socket(
       const unsigned short port, 
       TMatchCondition match_condition, 
       data_callback callback); 

      void listen(); 
      void stop(); 

     private: 
      tcp_socket(const tcp_socket&) = delete; 
      tcp_socket(tcp_socket&&)  = delete; 

      tcp_socket& operator=(const tcp_socket&) = delete; 
      tcp_socket& operator=(tcp_socket&&)  = delete; 

     private: 
      const utils::entry_exit   entry_exit_; 
      boost::asio::io_service   service_; 
      boost::asio::ip::tcp::acceptor acceptor_; 
      TMatchCondition     match_condition_; 
      data_callback     callback_; 
    }; 


    template <typename TMatchCondition> 
    tcp_socket<TMatchCondition>::tcp_socket(
     const unsigned short port, 
     TMatchCondition match_condition, 
     data_callback callback) 
     : entry_exit_("tcp_socket:" + std::to_string(port)) 
     , acceptor_(service_, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) 
     , match_condition_(match_condition) 
     , callback_(callback) {} 

    template <typename TMatchCondition> 
    void tcp_socket<TMatchCondition>::listen() 
    { 
     const auto port(acceptor_.local_endpoint().port()); 
     const std::string port_str(std::to_string(port)); 

     while(acceptor_.is_open()) 
     { 
      boost::system::error_code error; 

      utils::entry_exit ee("Listening on port " + port_str); 

      boost::asio::ip::tcp::socket socket(service_); 
      acceptor_.accept(socket, error); 

      if(error) 
      { 
       if(error != boost::asio::error::bad_descriptor) 
       { 
        LOG(ERROR) 
         << "An error occured while trying to accept a client connection; error=" 
         << error.message(); 

        sleep(1); // don't want to flood logs 
       } 
      } 
      else 
      { 
       while(socket.is_open()) 
       { 
        boost::asio::streambuf stream; 
        boost::asio::read_until(socket, stream, match_condition_, error); 

        const std::string msg(
         (std::istreambuf_iterator<char>(&stream)), 
         std::istreambuf_iterator<char>()); 

        LOG(INFO) << "Received message: " << msg; 

        boost::asio::write(
         socket, 
         boost::asio::buffer(callback_(msg)), 
         error); 

        if(error) 
        { 
         if(error != boost::asio::error::broken_pipe) 
         { 
          LOG(ERROR) 
           << "Error whilst writing response, closing client connection: " 
           << error.message(); 
         } 

         socket.close(); 

         sleep(1); // don't want to flood logs 
        } 
       } 
      } 
     } 
    } 


    template <typename TMatchCondition> 
    void tcp_socket<TMatchCondition>::stop() 
    { 
     boost::system::error_code error; 
     acceptor_.close(error); 

     if(error) 
     { 
      LOG(ERROR) << "Error whilst stopping TCP socket; error=" << error.message(); 
     } 
    }         

回答

2

我不认为你张贴的完整代码,但似乎问题是匹配条件:你指定使用boost::is_match_conditiontcp_socket_match_condition是匹配条件?

+0

这看起来是规范中的一个可选值(默认为“0”),这是必需的吗? – Graeme

+1

如果您想使用匹配条件使用过载,是的!该规范不是真正可选的:如果'boost :: is_match_condition :: value'的结果计算为'false',则重载将从重载集中移除,因为它会导致替换失败。你认为“可选”是用来确定第四个参数是什么的魔法。 –

+0

非常好,谢谢!将'typedef bool result_type'添加到'tcp_socket_match_condition'也解决了这个问题。 – Graeme

1

好的;所以叮当声(有点)在这里有帮助。

它告诉你有八个专业read_until,并且它不能使任何工作。

第三个参数为char,char和std :: string。这是行不通的。

最后三个参数有三个参数 - 您要传递四个参数。那些破旧的也不行。

中间留下两个。出于某种原因,您的TMatchCondition正在生成替代失败。

正如Dietmar刚刚指出的那样,您应该检查一下boost::is_match_condition<TMatchCondition>::value是否属实 - 因为如果不是这样,它将无法正常工作。

相关问题