c++ - 使用模板模板参数时的默认模板参数

标签 c++ templates c++11 language-lawyer emscripten

以下代码在 C++11 标准下使用 gcc 5.2、gcc 4.9 和 clang 3.7 编译:

template <typename T, typename U, template<typename...> class M>
U * find_item(M<T, U> & m, const T & t) {
  auto it = m.find(t);
  if (it != m.end()) { return &it->second; }
  return nullptr;
}

template <typename T, typename U, template<typename...> class M>
const U * find_item(const M<T, U> & m, const T & t) {
  auto it = m.find(t);
  if (it != m.end()) { return &it->second; }
  return nullptr;
}

#include <map>
#include <unordered_map>
#include <string>
#include <iostream>

int main() {
  std::map<std::string, int> foo;

  foo["asdf"] = 5;
  if (find_item(foo, std::string{"bar"})) { std::cerr << "hmm\n"; }
}

但是,当我用最新版本的 emscripten 编译它时,我得到一个编译器错误,源于 too few arguments for class template 'map' :

main.cpp:24:7: error: no matching function for call to 'find_item'
  if (find_item(foo, std::string{"bar"})) { std::cerr << "hmm\n"; }
      ^~~~~~~~~
main.cpp:2:5: note: candidate template ignored: substitution failure [with T =
      std::__1::basic_string<char>, U = int, M = map]: too few template
      arguments for class template 'map'
U * find_item(M<T, U> & m, const T & t) {
    ^         ~
main.cpp:9:11: note: candidate template ignored: substitution failure [with T =
      std::__1::basic_string<char>, U = int, M = map]: too few template
      arguments for class template 'map'
const U * find_item(const M<T, U> & m, const T & t) {
          ^               ~
1 error generated.
ERROR:root:compiler frontend failed to generate LLVM bitcode, halting

这有点奇怪,因为我的 emscripten 声称基于 clang-3.7。无论如何,在实例化 find_item 时似乎很难推断出默认参数。模板。

如果代码按以下方式更改,那么所有编译器似乎都会对此感到满意:

template <typename T, typename U, template<typename...> class M, typename... dummy>
U * find_item(M<T, U, dummy...> & m, const T & t) {
  auto it = m.find(t);
  if (it != m.end()) { return &it->second; }
  return nullptr;
}

template <typename T, typename U, template<typename...> class M, typename... dummy>
const U * find_item(const M<T, U, dummy...> & m, const T & t) {
  auto it = m.find(t);
  if (it != m.end()) { return &it->second; }
  return nullptr;
}

#include <map>
#include <unordered_map>
#include <string>
#include <iostream>

int main() {
  std::map<std::string, int> foo;

  foo["asdf"] = 5;
  if (find_item(foo, std::string{"bar"})) { std::cerr << "hmm\n"; }
}

问题是,根据 C++11 标准,“虚拟”部分实际上是必需的,还是 emscripten 有缺陷,因为这里没有计算出默认的模板参数?

我对第[temp.deduct.type] 14.8.2.6.8节的阅读是它应该能够绑定(bind) std::mapM<T, U> 形式的模板模板参数因为这句话中的“至少一个”的措辞:

Similarly, <T> represents template argument lists where at least one argument contains a T

但是,我不确定。

最佳答案

我遇到了这个问题,发现我不需要虚拟模板参数,将模板模板指定为可变参数就足够了(这是在 clang 3.6 上):

template <typename T, typename U, template<typename...> class M>
U * find_item(M<T, U> & m, const T & t) {
  auto it = m.find(t);
  if (it != m.end()) { return &it->second; }
  return nullptr;
}

template <typename T, typename U, template<typename...> class M>
const U * find_item(const M<T, U> & m, const T & t) {
  auto it = m.find(t);
  if (it != m.end()) { return &it->second; }
  return nullptr;
}

关于c++ - 使用模板模板参数时的默认模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34889583/

相关文章:

c++ - 可变函数模板基本案例 : without parameters or with one?

c++ - OpenCV,与教程中的代码进行特征匹配

c++ - 包含 boost 库时 undefined reference

c++ - 如何在 hpp 中声明一个 vector ?

c++ - 我可以根据其 operator() 的签名专门化可变参数模板参数吗

c++ - std::flush 未调用重写的 std::ostreamlush() 函数

c++ - 插入流的右值引用是否合理有效?

c++ - GlGenTextures 不断返回 0

c++ - 定义异常,它是如何工作的?

c++ - 不同类型的运算符