2013-10-31 97 views
0

使用位于命名空间下的操作数的运算符< <覆盖时,我遇到了错误。当MSVC2013编译(如需要)使用命名空间的Boost.Log错误

#ifndef ENUM_UTILS_H 
#define ENUM_UTILS_H 

#include <sstream> 
#include <unordered_map> 
#include <type_traits> 
#include <stdexcept> 
#include <algorithm> 

namespace sj 
{ 

template <typename T> 
struct enum_hasher 
{ 
    size_t operator()(T e) const 
    { 
     return static_cast<typename std::underlying_type<T>::type>(e); 
    } 
}; 

template <typename T> 
struct enum_strings 
{ 
    typedef const std::unordered_map<T, std::string, 
     enum_hasher<T>> maptype; 
    static maptype data; 
}; 

template <typename T> 
typename std::enable_if<std::is_enum<T>::value, std::string>::type 
enum_to_string(T e) 
{ 
    return enum_strings<T>::data.at(e); 
} 

template <typename T> 
typename std::enable_if<std::is_enum<T>::value, T>::type 
string_to_enum(const std::string& str) 
{ 
    auto& map = enum_strings<T>::data; 
    auto got = std::find_if(map.begin(), map.end(), 
    [&](const std::pair<T, std::string>& x) { return x.second == str; }); 

    if (got != map.end()) 
    { 
     return got->first; 
    } 
    std::stringstream ss; 
    ss << "conversion from " << str << " to enum failed"; 
    throw std::invalid_argument(ss.str()); 
} 


} // namespace sj 

/******* OPERATORS ON GLOBAL NS ********/ 

template <typename T> 
typename std::enable_if<std::is_enum<T>::value, std::ostream&>::type 
operator<<(std::ostream& os, T e) 
{ 
    return os << sj::enum_strings<T>::data.at(e); 
} 


#endif // ENUM_UTILS_H 


// logger.h 

#ifndef LOGGER_H 
#define LOGGER_H 

#include <boost/log/common.hpp> 


enum severity_level 
{ 
    sev_debug, 
    sev_info, 
    sev_warning, 
    sev_error, 
    sev_fatal 
}; 

// this macro returns the logger stream 
// example: LOG(debug) << "stuff to log"; 
#define LOG(lvl) BOOST_LOG_SEV(Logger::getLogger(), lvl) 

class Logger 
{ 
public: 
    typedef boost::log::sources::severity_logger<severity_level> MyLogger; 

    static void initialize(); 
    static MyLogger& getLogger() { return _logger; } 

private: 
    static bool _initialized; 
    static MyLogger _logger; 
}; 



#endif // LOGGER_H 


//// logger.cpp 




#include <iostream> 

#include "boost/log/common.hpp" 
#include "boost/log/expressions.hpp" 
#include "boost/log/utility/setup/file.hpp" 
#include "boost/log/utility/setup/console.hpp" 
#include "boost/log/utility/setup/common_attributes.hpp" 
#include "boost/log/attributes/timer.hpp" 
#include "boost/log/attributes/named_scope.hpp" 
#include "boost/log/sources/logger.hpp" 
#include "boost/log/support/date_time.hpp" 

bool Logger::_initialized = false; 
Logger::MyLogger Logger::_logger = Logger::MyLogger(); 

template< typename CharT, typename TraitsT > 
inline std::basic_ostream< CharT, TraitsT >& operator<< (
    std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl) 
{ 
    static const char* const str[] = 
    { 
     "debug", 
     "info", 
     "warning", 
     "error", 
     "fatal" 
    }; 
    if (static_cast<std::size_t>(lvl) < (sizeof(str)/sizeof(*str))) 
     strm << str[lvl]; 
    else 
     strm << static_cast<int>(lvl); 
    return strm; 
} 



#include <string> 

enum class TestEnum 
{ 
    ValA, 
    ValB 
}; 

template<> sj::enum_strings<TestEnum>::maptype 
    sj::enum_strings<TestEnum>::data = 
{ 
    {TestEnum::ValA, "ValA"}, 
    {TestEnum::ValB, "ValB"} 
}; 

namespace myns 
{ 

enum class TestEnumNS 
{ 
    ValC, 
    ValD 
}; 

} 

template<> sj::enum_strings<myns::TestEnumNS>::maptype 
    sj::enum_strings<myns::TestEnumNS>::data = 
{ 
    {myns::TestEnumNS::ValC, "ValC"}, 
    {myns::TestEnumNS::ValD, "ValD"} 
}; 


int main() 
{ 
    LOG(sev_debug) << TestEnum::ValB; 
    std::cout << TestEnum::ValB << std::endl; 

    // this line doesn't compile for some reason! 
    LOG(sev_debug) << myns::TestEnumNS::ValC; 
    // std::cout works without problems 
    std::cout << myns::TestEnumNS::ValC << std::endl; 

    return 0; 
} 

完全编译日志:我真的不甚至不确定什么可能导致这个问题,请看看源代码

C:\build-env\boost\master\include\boost/log/utility/formatting_ostream.hpp(710) : error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const myns::TestEnumNS' (or there is no acceptable conversion) 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(498): could be 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_streambuf<char,std::char_traits<char>> *)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(478): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(const void *)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(458): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long double)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(438): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(double)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(418): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(float)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(397): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned __int64)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(377): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(__int64)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(356): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned long)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(336): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(316): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned int)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(291): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(int)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(271): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned short)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(237): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(short)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(217): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::_Bool)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(210): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::ios_base &(__cdecl *)(std::ios_base &))' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(203): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_ios<char,std::char_traits<char>> &(__cdecl *)(std::basic_ios<char,std::char_traits<char>> &))' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(197): or  'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_ostream<char,std::char_traits<char>> &(__cdecl *)(std::basic_ostream<char,std::char_traits<char>> &))' 
     C:\build-env\boost\master\include\boost/log/attributes/attribute_name.hpp(175): or  'std::basic_ostream<char,std::char_traits<char>> &boost::log::v2s_mt_nt5::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const boost::log::v2s_mt_nt5::attribute_name &)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(699): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(746): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(784): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(831): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(957): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const signed char *)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(964): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,signed char)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(971): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const unsigned char *)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(978): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,unsigned char)' 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(988): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>,myns::TestEnumNS>(std::basic_ostream<char,std::char_traits<char>> &&,const _Ty &)' 
     with 
     [ 
      _Ty=myns::TestEnumNS 
     ] 
     C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\ostream(1026): or  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const std::error_code &)' 
     while trying to match the argument list '(std::basic_ostream<char,std::char_traits<char>>, const myns::TestEnumNS)' 
     ..\BoostLogTest\boostlogtest.cpp(190) : see reference to function template instantiation 'boost::log::v2s_mt_nt5::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>> &boost::log::v2s_mt_nt5::operator <<<char,std::char_traits<char>,std::allocator<char>,myns::TestEnumNS>(boost::log::v2s_mt_nt5::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>> &,const T &)' being compiled 
     with 
     [ 
      T=myns::TestEnumNS 
     ] 

是Boost.Log中有一个错误,或者我做错了什么?

升压版本是1.55。

+0

请发表*完整*错误日志,它可能有更多的线索,关于编译器真正想要的。 –

+0

Joachim Pileborg,请再看一下。包括完整的错误日志。 –

回答

3

失败操作员查找不直接操作者在这里:

LOG(sev_debug) << myns::TestEnumNS::ValC; 

但是,正如铛++所说的那样:

/usr/local/include/boost/log/utility/formatting_ostream.hpp:664:19: error: invalid operands to binary expression ('ostream_type' (aka 'basic_ostream') and 'myns::TestEnumNS')

strm.stream() << value; 
~~~~~~~~~~~~~^~~~~~ 

这种表达可能不在全局命名空间中找到operator<<功能,如果围绕此表达式的命名空间中的任何其他重载将停止未限定的查找。

仔细看看文件formatting_ostream.hpp,该表达式出现在boost::log命名空间中。 boost::logboost名称空间中名称为operator<<的任何函数将停止未限定的查找,并且将阻止从找到在全局名称空间处声明的operator<<的不合格查找。

您应该以可通过ADL找到的方式为您的操作员提供服务,例如,

namespace myns 
{ 

    enum class TestEnumNS 
    { 
     ValC, 
     ValD 
    }; 

    using ::operator<<; 

} 

N.B.我目前不完全确定这是否足够,或者您是否必须在男士手中编写适当的功能。铿锵++编译代码与此添加但发出大量的链接器错误。