安answer to C++14 Variable Templates: what is the purpose? Any usage example?提出了一个变量模板 + 通用 lambda 的用法示例,看起来像这样:
void some_func() {
template<typename T>
std::map<int, T> storage;
auto store = []<typename T>(int key, const T& value) { storage<T>.insert(key, value) };
store(0, 2);
store(1, "Hello"s);
store(2, 0.7);
// All three values are stored in a different map, according to their type.
}
不幸的是它没有编译,所以我试图“修复”它,这是我目前的尝试。
#include <map>
template<typename T>
std::map<int, T> storage;
void some_func() {
auto store = [](int key, const auto& value) { storage<decltype(value)>.insert(key, value); };
store(0, 2);
store(1, std::string("Hello"));
store(2, 0.7);
}
错误信息是:
main.cpp:7:76: error: no matching member function for call to 'insert'
auto store = [](int key, const auto& value) { storage<decltype(value)>.insert(key, value); };
~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
main.cpp:10:10: note: in instantiation of function template specialization 'some_func()::<anonymous class>::operator()<std::basic_string<char> >' requested here
store(1, std::string("Hello"));
当你实例化一个变量模板时,就像所有的模板一样,每个变量都是不同的类型。理论是 auto
不会针对每种类型推导,但最初只会推导一种类型( double )。因此代码无效。即使这可以工作,存储的每个实例化都将引用不同的变量。
如何重写这段代码才能达到初衷?
编辑 我在编辑中犯了一个小错误(查看修订历史以避免文本墙。)decltype(pair)
应该是 decltype(pair. second)
因为storage
只有一个模板参数。
#include <map>
template <typename T>
std::map<int, T> storage;
void some_func() {
auto store = [&](auto pair) { storage<decltype(pair.second)>.insert(pair); };
store(std::pair<int, int>(0, 1));
store(std::pair<int, std::string>(1, "Hello!"));
store(std::pair<int, int>(2, 3));
}
int main()
{
}
现在有链接器错误。
/tmp/main-5f1f7c.o: In function `some_func()':
main.cpp:(.text+0x1a): undefined reference to `storage<int>'
main.cpp:(.text+0x43): undefined reference to `storage<std::string>'
main.cpp:(.text+0x74): undefined reference to `storage<int>'
为了修复链接器错误,我认为您需要显式实例化参数? (我什至不确定这是否是正确的术语。)
template <typename T>
std::map<int, T> storage;
template <>
std::map<int, int> storage<int>;
template <>
std::map<int, std::string> storage<std::string>;
最佳答案
template<typename T>
std::map<int, T> storage;
这是一个声明,很像例如template<typename T> class foo;
.无论如何我们都需要一个定义,我们也会从定义中受益:
template<typename T>
std::map<int, T> storage {};
但这并没有消除链接器错误,这表明隐式实例化存在一个突出的错误。为了说服自己,我们可以通过多种方式触发实例化:
明确地,这看起来像
// namespace scope, same as storage template /* sic */ std::map<int, int> storage<int>; template std::map<int, std::string> storage<std::string>;
隐式地,通过在
main
中添加以下内容storage<int>.size(); storage<std::string>.size();
在任何一种情况下都驯服链接器。
您尝试的是显式特化,虽然使用不同的机制,但确实解决了这个问题。
关于c++ - 变量模板 + std::map 的通用 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21188052/