2013-06-05 4 views
1

unique_ptr 형식이 C++ 11에서 템플릿과 얼마나 잘 작동하는지 파악하려고하는데 많은 행운이 없습니다. 특히 템플릿 함수를 삽입하려고합니다. a 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

'remove_reference &> :: type'입니다 중복 ... – 0x499602D2

+0

이해가 안 : 왜'remove_reference &> : type'이 아니라 'unique_ptr '? –

+0

좋아, 그거 이상해. 그걸로 놀고 다니는 동안 나는 그것을 필요로한다고 생각했지만, 단지'unique_ptr '으로 컴파일하는 것 같다. ... – errantlinguist

답변

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 disambiguator을 사용하지 않는 것이 가장 가능성이 점점 컴파일러 오류의 원인은 다음과 같습니다

:

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에서 더 이상 사용되지 않습니다.

+0

아, 그리고 예외 사양에 대해 감사드립니다. 아무 래도 큰소리로 표기하지 않았습니다. – errantlinguist

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

은 복사 할 수 없도록해야한다 단순히 이동 매개 변수에 어떤 lvalues. 예를 들어, 본문에 유효하지 않은 행이 있습니다. 이 변경 :

moveValueForUniqueKey(testMap, key1, move(val2)); 

moveValueForUniqueKey(move(testMap), key1, move(val2)); 
//     ^^^^^^^^^^^^^ 
+0

감사합니다; 'remove_reference :: type' 말도 안되는 소리는 지금 잠을 좀 자야한다는 것을 의미합니다 ... – errantlinguist

+0

'move (ObjectMap, K key, unique_ptr 값) throw (char)'가 컴파일되지 않습니다. 내 컴퓨터 : '삭제 된 함수의 사용 'constexpr std :: pair <_T1, _T2> :: pair (const std :: pair <_T1, _T2> &) [_T1 = const char, _T2 = std :: unique_ptr , std :: pair와 함께 <_T1, _T2> = std :: pair >]' – errantlinguist

+0

예 : 내부적으로'unordered_map'에 의해 사용됩니다. – errantlinguist