gpt4 book ai didi

c++ - 为什么即使是 ""也必须使用 std::string() 来满足模板参数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:57:14 24 4
gpt4 key购买 nike

我编写了一个非常简单的模板来标记字符串,如下所示。

但是,我在调用该函数时遇到问题,我不能将 C 字符串用于 delimiterstrim_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();
}

最佳答案

规则是,当你有三个 StringT const & 参数时,StringT 是独立于相应的参数推导的,推导的类型必须匹配。

你可以

  • 如果希望容器的值类型是正确的字符串类型,则只需对所有三个使用 typename ContainerT::value_type;或
  • block 从三个 StringT 中的两个中推导 StringT - 获取参数,

    • 要么在调用点通过使用 braced-init-lists 使后两个参数成为非推导上下文:

      int count = tokenize_string(tokens, str, {","}, true, {" "});
    • 或者在函数模板本身中,通过将后两个 StringT 参数包装到非推导上下文中:

      template < class StringT, class ContainerT >
      size_t tokenize_string(ContainerT & tokens
      , StringT const & str
      , typename std::decay<StringT>::type const & delimiters
      , bool const trim_empty = false
      , typename std::decay<StringT>::type const & trim_string = StringT())
  • 或者为每个取不同的类型参数,稍后在函数模板主体中协调它们。

关于c++ - 为什么即使是 ""也必须使用 std::string() 来满足模板参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38338505/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com