【发布时间】:2016-11-15 06:19:43
【问题描述】:
我写了一个非常简单的模板来标记一个字符串,如下所示。
但是,我在调用该函数时遇到问题,我不能将 C 字符串用于 delimiters 或 trim_string 参数。这些必须是std::string(或任何类型的字符串StringT,即std::wstring)。
所以以下失败:
std::vector<std::string> tokens;
std::string str = "This string, it will be split, in 3.";
int count = tokenize_string(tokens, str, ",", true, " ");
为了解决这个问题我必须写:
std::vector<std::string> tokens;
std::string str = "This string, it will be split, in 3.";
int count = tokenize_string(tokens, str,
std::string(","), true, std::string(" "));
在这种情况下,有没有办法避免在标准 C 字符串周围使用 std::string()?
我在使用 g++ 时遇到的错误如下所示:
/home/snapwebsites/snapwebsites/snapmanagercgi/daemon/snapmanagerdaemon.cpp: In member function ‘void snap_manager::manager_daemon::init(int, char**)’:
/home/snapwebsites/snapwebsites/snapmanagercgi/daemon/snapmanagerdaemon.cpp:103:71: error: no matching function for call to ‘tokenize_string(std::vector<std::__cxx11::basic_string<char> >&, const string&, const char [2], bool, const char [2])’
snap::tokenize_string(f_bundle_uri, bundle_uri, ",", true, " ");
^
In file included from /home/snapwebsites/snapwebsites/snapmanagercgi/daemon/snapmanagerdaemon.cpp:35:0:
/home/snapwebsites/BUILD/dist/include/snapwebsites/tokenize_string.h:46:8: note: candidate: template<class StringT, class ContainerT> size_t snap::tokenize_string(ContainerT&, const StringT&, const StringT&, bool, const StringT&)
size_t tokenize_string(ContainerT & tokens
^
/home/snapwebsites/BUILD/dist/include/snapwebsites/tokenize_string.h:46:8: note: template argument deduction/substitution failed:
/home/snapwebsites/snapwebsites/snapmanagercgi/daemon/snapmanagerdaemon.cpp:103:71: note: deduced conflicting types for parameter ‘const StringT’ (‘std::__cxx11::basic_string<char>’ and ‘char [2]’)
snap::tokenize_string(f_bundle_uri, bundle_uri, ",", true, " ");
^
模板:
template < class StringT, class ContainerT >
size_t tokenize_string(ContainerT & tokens
, StringT const & str
, StringT const & delimiters
, bool const trim_empty = false
, StringT const & trim_string = StringT())
{
for(typename StringT::size_type pos(0), last_pos(0); last_pos < str.length(); last_pos = pos + 1)
{
pos = str.find_first_of(delimiters, last_pos);
// no more delimiters?
//
if(pos == StringT::npos)
{
pos = str.length();
}
char const * start(str.data() + last_pos);
char const * end(start + (pos - last_pos));
if(start != end // if not (already) empty
&& !trim_string.empty()) // and there are characters to trim
{
// find first character not in trim_string
//
start = std::find_if_not(
start
, end
, [&trim_string](auto const c)
{
return trim_string.find(c) != StringT::npos;
});
// find last character not in trim_string
//
if(start < end)
{
reverse_cstring<typename StringT::value_type const> const rstr(start, end);
auto p = std::find_if_not(
rstr.begin()
, rstr.end()
, [&trim_string](auto const c)
{
return trim_string.rfind(c) != StringT::npos;
});
end = p.get();
}
}
if(start != end // if not empty
|| !trim_empty) // or user accepts empty
{
tokens.push_back(typename ContainerT::value_type(start, end - start));
}
}
return tokens.size();
}
【问题讨论】:
-
tokens和str的类型有哪些? -
尝试在字符串前面加上一个 S 或一个小写的 s(我忘记了这些文字的真实含义)或附加。我不确定语法。可以是
S","或s","或","S或","s(试试看哪个不会出现语法错误) -
@PaulStelian 是后记小写 s,你需要
using namespace std::literals或类似的东西。 -
@PaulStelian it's
","s -
@PaulStelian,你是对的。这样可行。虽然据我回忆,这与
std::string(...)的作用相同,但它只是使用 C++11 中的一个新特性来隐藏它。不过,我想在这种情况下这很实用!
标签: c++ string templates c++11