显然,向 std
添加( almost )任何内容是未定义的行为命名空间。
我正在使用没有 std::chrono::parse()
的 C++14 (仅限 C++20)但我需要反序列化 std::chrono::milliseconds
类型的值(std::chrono::duration
的特化)来自 istream
.
虽然这可行,但我找不到任何允许这不是 UB 的异常(exception)情况:
namespace std {
std::istream& operator >>(std::istream & is, std::chrono::milliseconds & ms) {
std::string s;
is >> s;
ms = std::chrono::milliseconds(std::stoi(s));
return is;
}
}
因为这两个参数类型都不是我的类型,所以我不确定如何在 std
之外安全地定义这个运算符命名空间。
请注意,运算符将在 Boost::program_options
的深处调用所以我不认为我可以在我自己的命名空间中定义运算符然后使用 using my_ns::operator>>
因为using
的范围声明不会扩展到 program_options
范围。
我是怎么走到这一步的
作为 Boost::program_options
的用户我有一个特定的配置变量,它是从存储为 std::chrono::milliseconds
的配置文件中读取的。值:
std::chrono::milliseconds period;
po::options_description config_only_opts;
config_only_opts.add_options()
("control.period", po::value<std::chrono::milliseconds>(&period), "Specify the period in milliseconds");
// ...
auto istream = ifstream("config.cfg");
po::variables_map vm;
po::store(po::parse_config_file(istream, config_file_opts, false), vm);
根据Boost::program_options
文档,可以从配置文件中反序列化具有 operator >> (istream &, ...)
类型的值函数定义。
没有扩展到 std
上面提到的,我最终遇到了这种编译器错误:
/home/david/opt/boost-1.69/include/boost/lexical_cast/detail/converter_lexical.hpp: In instantiation of ‘struct boost::detail::deduce_target_char_impl<boost::detail::deduce_character_type_later<std::chrono::duration<long int, std::ratio<1, 1000> > > >’:
/home/david/opt/boost-1.69/include/boost/lexical_cast/detail/converter_lexical.hpp:270:89: required from ‘struct boost::detail::deduce_target_char<std::chrono::duration<long int, std::ratio<1, 1000> > >’
/home/david/opt/boost-1.69/include/boost/lexical_cast/detail/converter_lexical.hpp:407:92: required from ‘struct boost::detail::lexical_cast_stream_traits<std::__cxx11::basic_string<char>, std::chrono::duration<long int, std::ratio<1, 1000> > >’
/home/david/opt/boost-1.69/include/boost/lexical_cast/detail/converter_lexical.hpp:468:15: required from ‘struct boost::detail::lexical_converter_impl<std::chrono::duration<long int, std::ratio<1, 1000> >, std::__cxx11::basic_string<char> >’
/home/david/opt/boost-1.69/include/boost/lexical_cast/try_lexical_convert.hpp:201:44: required from ‘bool boost::conversion::detail::try_lexical_convert(const Source&, Target&) [with Target = std::chrono::duration<long int, std::ratio<1, 1000> >; Source = std::__cxx11::basic_string<char>]’
/home/david/opt/boost-1.69/include/boost/lexical_cast.hpp:41:60: required from ‘Target boost::lexical_cast(const Source&) [with Target = std::chrono::duration<long int, std::ratio<1, 1000> >; Source = std::__cxx11::basic_string<char>]’
/home/david/opt/boost-1.69/include/boost/program_options/detail/value_semantic.hpp:92:36: required from ‘void boost::program_options::validate(boost::any&, const std::vector<std::__cxx11::basic_string<charT> >&, T*, long int) [with T = std::chrono::duration<long int, std::ratio<1, 1000> >; charT = char]’
/home/david/opt/boost-1.69/include/boost/program_options/detail/value_semantic.hpp:184:21: required from ‘void boost::program_options::typed_value<T, charT>::xparse(boost::any&, const std::vector<std::__cxx11::basic_string<charT> >&) const [with T = std::chrono::duration<long int, std::ratio<1, 1000> >; charT = char]’
/home/david/myproj/Config.cpp:208:1: required from here
/home/david/opt/boost-1.69/include/boost/lexical_cast/detail/converter_lexical.hpp:243:13: error: static assertion failed: Target type is neither std::istream`able nor std::wistream`able
BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value),
^
最佳答案
即使标准允许运算符重载,我也不建议添加该函数。这不是从 std::istream
读取 std::chrono::milliseconds
的通用方法。您所拥有的是您的应用程序自己从 std::istream
中读取此类对象的方式。
我建议在您的应用程序自己的命名空间
中添加一个函数。
namespace MyApp
{
std::istream& readChronoMilliSeconds(std::istream& is, std::chrono::milliseconds & ms)
{
std::string s;
is >> s;
ms = std::chrono::milliseconds(std::stoi(s));
return is;
}
}
关于c++ - 如何在不扩展命名空间 `std` 的情况下为缺少预定义运算符的标准类型定义运算符 >> (istream &, ...)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58924211/