以下代码在 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::map
到 M<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/