使用char const *的变量模板

时间:2014-06-10 07:14:16

标签: c++ templates c++11 variadic-templates

我想创建一个类来验证几个字符串或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;

};

然后在主要方面我尝试了类似的东西:

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

或者

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

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

1 个答案:

答案 0 :(得分:3)

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

  

常量表达式(   5.19)指定具有静态存储持续时间和外部或内部链接的对象的地址或具有外部的功能   或内部联系,包括功能模板和功能   表达式,但不包括非静态类成员   (忽略括号)和&amp; id-expression,除了&amp;也许   如果名称引用函数或数组,则省略,并省略   如果相应的模板参数是参考

您显示的两个示例用法都不匹配,另一方面这些是正常的:

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;
};