带char const*的可变进值模板

Variadic template with char const*

本文关键字:char const      更新时间:2023-10-16

我想创建一个类来验证几个字符串或char const *的查找结果。我期望因为"某物"是常量,它将工作,或者即使我将其声明为静态const参数。不幸的是,这不起作用…有人觉得这门课有什么问题吗?

template<char const*... Args_t>
struct Finder {
   Finder() {
      Add<Args_t...>();
      m_len = sizeof...(Args_t);
      m_count = 0;
   }
   void Append(char const* key, string val) {
       Found_t::iterator found = m_founds.find(key);
       if (key == m_founds.end()) return; // irrelevant
       if (!found->second.empty()) {
           stringstream str;
           str << "Found an already existing key: [" << key << ']' << endl;
           throw logic_error(str.str());
       }
       found ->second = std::move(val);
       ++m_count;
   }
   bool Complete() { return m_len == m_count; }
private:
   template<char const* First_t, char const*... Rest_t> void Add() {
       m_founds.insert(Found_t::value_type(First_t, ""));
       Add<Rest_t...>();
   }
   template<char const* Last_t> void Add() {
       m_founds.insert(Found_t::value_type(Last_t, ""));
   }
   typedef std::map<char const*, string> Found_t;
   Found_t m_founds;
   int m_len;
   int m_count;
};

,然后在main中我尝试了如下内容:

Finder<"firstStr", "secondStr"> finder;

  static const char const* s_first = "first";
    static const char const* s_second = "second";
    Finder<s_first, s_second> finder;

我得到的错误是:表达式必须有一个常量

非类型模板参数必须遵守一些规则,基本上它必须是唯一的(具有外部链接曾经是其中之一,但正如Constructor在注释中指出的那样,这不再是完全正确的)-标准的相关部分:

一个常量表达式(5.19),用于指定具有静态存储时间和外部或内部链接的对象或具有外部链接的函数的地址或内部链接,包括函数模板和函数模板id,但不包括非静态类成员(忽略括号)作为&id-表达式,除了&可能是如果名称涉及函数或数组,则省略,应省略如果对应的模板参数是引用

您展示的两个示例用法不匹配,另一方面,这些都是可以的:

extern const char s_first[] = "first";
static constexpr char s_second[] = "second";
Finder< s_first, s_second > f;

编辑

你的样本有几个其他问题(Add的模糊定义,比较keym_founds.end(),正确的版本由Jarod42:

template<char const*... Args_t>
struct Finder {
Finder() {
  Add<Args_t...>();
  m_len = sizeof...(Args_t);
  m_count = 0;
}
void Append(char const* key, string val) {
  Found_t::iterator found = m_founds.find(key);
  if (found == m_founds.end()) return; // irrelevant
  if (!found->second.empty()) {
    stringstream str;
    str << "Found an already existing key: [" << key << ']' << endl;
    throw logic_error(str.str());
  }
  found ->second = std::move(val);
  ++m_count;
}
bool Complete() { return m_len == m_count; }
private:
  template<char const* First_t, char const* Second_t, char const*... Rest_t> void Add() {
    m_founds.insert(Found_t::value_type(First_t, ""));
    Add<Second_t, Rest_t...>();
  }
  template<char const* Last_t> void Add() {
    m_founds.insert(Found_t::value_type(Last_t, ""));
  }
  typedef std::map<char const*, string> Found_t;
  Found_t m_founds;
  int m_len;
  int m_count;
};