2012-11-21 100 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是否屬實 - 因爲如果不是這樣,它將無法正常工作。

相關問題