我正在试图弄清楚unique_ptr
类型在C ++ 11中使用模板的确切方式,并且没有太多运气:具体来说,我正在尝试创建一个插入{的模板函数{1}}如果地图中的键没有值,则给定地图中给定唯一键的值,并将unique_ptr
指向的值的所有权移动到地图中的值;如果密钥已存在,则抛出运行时错误。
现在,如果您不必将unique_ptr
传递给函数,那么移动unique_ptr
的值非常简单:
#include <iostream>
#include <memory>
#include <unordered_map>
using namespace std;
int main(int argc, char *argv[])
{
unordered_map<char, unique_ptr<int> > testMap;
char key1 = 'A';
unique_ptr<int> val1(new int(1));
testMap[key1] = move(val1);
// Print the results
cout << "testMap[" << key1 << "] = " << *testMap[key1] << endl;
return 0;
}
将unique_ptr
传递给函数有点复杂:
#include <iostream>
#include <memory>
#include <unordered_map>
using namespace std;
void moveValueForUniqueKey(unordered_map<char, unique_ptr<int> >& targetMap, char key, unique_ptr<int> value) throw(char)
{
// Check if the key is already in the map
auto it = targetMap.find(key);
if (it != targetMap.end())
{
throw key;
}
else
{
targetMap[key] = move(value);
}
}
int main(int argc, char *argv[])
{
unordered_map<char, unique_ptr<int> > testMap;
char key1 = 'A';
unique_ptr<int> val1(new int(1));
// Try inserting the first key-value pair
try
{
moveValueForUniqueKey(testMap, key1, move(val1));
}
catch (char& duplicateKey)
{
cerr << "Key '" << duplicateKey << "' already in map." << endl;
}
// Print the key-value pairs
for (pair<const char, unique_ptr<int> >& entry : testMap)
{
cout << "testMap['" << entry.first << "'] = " << *entry.second << endl;
}
unique_ptr<int> val2(new int(2));
// Try inserting the key again
try
{
moveValueForUniqueKey(testMap, key1, move(val2));
}
catch (char& duplicateKey)
{
cerr << "Key '" << duplicateKey << "' already in map." << endl;
}
// Print the key-value pairs again
for (pair<const char, unique_ptr<int> >& entry : testMap)
{
cout << "testMap['" << entry.first << "'] = " << *entry.second << endl;
}
return 0;
}
此代码输出:
testMap['A'] = 1
Key 'A' already in map.
testMap['A'] = 1
现在,当我尝试创建此函数的模板时,将moveValueForUniqueKey(...)
的先前声明/实现替换为:
template<typename K, typename V, typename M>
void moveValueForUniqueKey(M targetMap, K key, unique_ptr<V> value) throw(char)
{
// Check if the key is already in the map
auto it = targetMap.find(key);
if (it != targetMap.end())
{
throw key;
}
else
{
targetMap[key] = move(value);
}
}
// Instantiate template function
template
void moveValueForUniqueKey(unordered_map<char, unique_ptr<int> >& targetMap, char key, unique_ptr<int> value) throw(char);
我只是得到了编译器错误use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const char, _T2 = std::unique_ptr<int>, std::pair<_T1, _T2> = std::pair<const char, std::unique_ptr<int> >]’
。
这里究竟发生了什么,你怎么能完成我在这里尝试的东西(使用移动语义将unique_ptr
个对象传递给模板函数)?
答案 0 :(得分:1)
首先,这个:
remove_reference<unique_ptr<int>&>::type
就等于这个:
unique_ptr<int>
我认为那里不需要remove_reference
。要说服自己,请尝试以下方法:
#include <type_traits>
#include <memory>
static_assert(std::is_same<
remove_reference<unique_ptr<int>&>::type,
unique_ptr<int>>::value, "!");
你会看到断言没有触发(live example)。
您获得编译器错误的原因很可能是您没有在函数模板中使用typename
消歧器:
template<typename K, typename V, typename M>
void moveValueForUniqueKey(M targetMap, K key,
typename remove_reference<unique_ptr<V>&>::type value) throw(char)
// ^^^^^^^^
{
// ...
}
但同样,没有理由在那里使用remove_reference
:
template<typename K, typename V, typename M>
void moveValueForUniqueKey(M targetMap, K key, unique_ptr<V> value) throw(char)
// ^^^^^^^^^^^^^
{
// ...
}
最后,请记住,在C ++ 11中不推荐使用动态异常规范。
答案 1 :(得分:1)
首先,您需要typename
,因为您通过模板参数获取类型:
template<typename K, typename V, typename M>
void moveValueForUniqueKey(
M targetMap, K key, typename remove_reference<unique_ptr<V>&>::type value) throw(char)
// ^^^^^^^^
{...}
但您不需要签名remove_refrence<T&>::type
。你为什么不只是使用T
?
template<typename K, typename V, typename M>
void moveValueForUniqueKey(M targetMap, K key, unique_ptr<V> value) throw(char)
{...}
无法复制 std::unique_ptr
,因此您只需将任何左值移动到参数中即可。例如,您的主页中包含无效行。改变这个:
moveValueForUniqueKey(testMap, key1, move(val2));
到这个
moveValueForUniqueKey(move(testMap), key1, move(val2));
// ^^^^^^^^^^^^^