【发布时间】:2014-02-06 21:51:13
【问题描述】:
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 不会为每种类型推导出来,但最初只有一种类型(双)。因此代码无效。即使这可以工作,每个存储实例都会引用不同的变量。
如何重写这段代码以达到最初的意图?
编辑我在编辑中犯了一个小错误(请参阅修订历史记录以避免出现文字墙。)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>;
【问题讨论】:
-
你能概括地描述一下最初的意图是什么吗?也就是说,我们尝试使用这样的代码实现的想法是什么?
-
你也确定你的编译器支持变量模板吗?
-
@PlasmaHH 我正在使用 Coliru,它有 clang 3.5。
-
我认为问题在于:这不是一个捕获 lambda,所以映射(即使它是一个全局变量)没有被 lambda 捕获。
-
Lambda 签名是对的??? lambda 不应该是:
auto store = [&] (decltype(storage)::value_type val) { storage.insert(val); };