使用模板模板参数时的默认模板参数

时间:2016-01-20 00:43:55

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

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

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

问题是,如果&#34;虚拟&#34;根据C ++ 11标准实际上是必要的部分,还是emscripten有缺陷而没有在这里找出默认的模板参数?

我对[temp.deduct.type] 14.8.2.6.8部分的解读是,它应该能够将std::map绑定到M<T, U>形式的模板模板参数,因为措辞&#34;至少有一个&#34; 34;在这句话中:

  

类似地,&lt; T&gt;代表模板参数   列出至少一个参数包含T

的列表

但是,我对此并不确定。

1 个答案:

答案 0 :(得分:1)

我遇到了这个问题,发现我不需要虚拟模板参数,指定模板模板为variadic就足够了(这是在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;
}
相关问题