2013-01-21 2 views
8

VC++의 약간 덜 오래된 버전 인 2010에 코드를 이식하는 데 문제가 있습니다. vc2010의지도 값 유형에 대한 멤버에 대한 포인터 만들기

이슈

non-type-argument에서 pointer-to-member의 유도베이스로의 변환 결과 VC지도의 구현에 의해 발생이 요구되고 :

#include <map> 
#include <algorithm> 

template <typename MapValueType, int MapValueType::*var> 
bool f (MapValueType const & v); 

int main() 
{ 
    typedef std :: map<int, int> MapType; 
    MapType m; 
    std :: find_if (m.begin() 
     , m.end() 
     , f<MapType::value_type, & MapType::value_type::second>); 
} 

다음 메시지가 생성된다 :

포인터 투 부재 염기로부터

표준 변환 가리키는 포인터 부재 템플릿 인수 file.cc (X)에 대한인가되지 유도의 오류 C2973 : 'F': 유효 템플릿 인수 '내부의 표준 : _ Pair_base,321 0 _Ty1, _Ty2는> :: * '

는 그래서 std::map에서 value_type의 구현은 기본 클래스의 쌍 것 같다.

를 해결하고non-type-argumentpointer-to-member을 유지하는 방법에 어떤 아이디어?

구조가 변경되어 ffunctor이고 구성원이 pointer-to-member 인 유일한 이유는 무엇입니까?

+1

어쩌면 어리석은 질문 일지 모르지만 그 포인터를 회원에게 전달해야하는 이유는 무엇입니까? –

+0

'::'및 다른 어휘 토큰을 둘러싼 공백은 무엇입니까? – TemplateRex

+0

그래, 바로 앞의 질문을 명확히하는 이유는 간단'템플릿 <유형 이름 MapItemType> 부울 F (MapItemType의 CONST & v);'당신을 위해 작동하지 않습니다 –

답변

3

decltype()이 코드는 IMO 컴파일해야한다는 제공 (그리고 GCC 4.7에 함께 않습니다 비주얼 스튜디오 2010 또는 컴파일러 중 하나를 제한 할 수 있습니다 경우,이 사용할 수 있다고 생각합니다. 2 및 Clang 3.2), 나는 당신의 디자인이 불필요하게 복잡하다고 믿습니다. pair에는 두 개의 멤버 변수 만 있으므로 첫 번째 또는 두 번째 중 하나에 액세스하게됩니다.

functor 객체가 필요하지 않습니다. 부울 템플릿 인수를 사용하여 코드가 first 또는 second 멤버 변수에서 작동하는지 확인하십시오. 다음은 가능성이다 :

#include <map> 
#include <algorithm> 

template <typename MapValueType, bool first> 
bool f (MapValueType const & p) 
{ 
    auto& v = (first) ? p.first : p.second; 
    // ... do your work on v ...  
} 

int main() 
{ 
    typedef std :: map<int, int> MapType; 
    MapType m; 

    // Will work on the `first` member 
    std::find_if(m.begin(), m.end(), f<MapType::value_type, true>); 

    // Will work on the `second` member 
    std::find_if(m.begin(), m.end(), f<MapType::value_type, false>); 
} 

당신이 정말로 당신의 클라이언트 코드 나 f() 함수 내에서 코드를 변경할 수없는 경우, 당신은이 VS2010 특정 해킹 갈 수있는 다음과 같은 경우,

// Add "_MyBase" here... works, but ugly IMO 
template <typename MapValueType, int MapValueType::_Mybase::* var> 
bool f(MapValueType const & v); 

// And the client side could stay unchanged... 
int main() 
{ 
    typedef std :: map<int, int> MapType; 
    MapType m; 
    std::find_if(
     m.begin(), 
     m.end(), 
     f<MapType::value_type, &MapType::value_type::second> 
     ); 
} 

마지막으로 당신의 코드가 다른 플랫폼 와 함수의 클라이언트 코드는 여전히 보유의 비 수정 가능성에 모든 제약 조건에 컴파일 할 수있다, 당신은 VS2010과 다른 컴파일러에 대한 빈 문자열로 _Mybase::로 확장 전 처리기 매크로를 정의 할 수 있습니다.

+0

답변 해 주셔서 감사합니다 (+1). 문제를 묻는 동기 중 일부는 더 이상 작동하지 않는다는 사실에 놀랐습니다. 이것이 변경할 수없는 API의 일부인 경우 - 어떻게 해결할 수 있습니까? –

+0

@RichardCorden : 해결 방법으로 답변을 업데이트했습니다. (솔직히 말해서, VS2010에 강력하게 적용되었으므로 ... 음, 결국 사용자에게 달려 있습니다.) –

+0

bool 또는 이 경로를 가기 전에 멤버는 g ++로 컴파일해야합니다. –

4

왜 비 타입 템플릿 매개 변수/인수로 포인터 - 투 - 회원 유지를 주장합니까?

어쨌든, 난 당신이

template <typename Class, typename Type> 
Class 
get_class_type (Type Class:: *); 
//... 
it = std::find_if(m.begin(), m.end(), 
    f<decltype(get_class_type(&MapType::value_type::second)), &MapType::value_type::second>); 
+1

짧은 대답은 내가 알고있는 코드를 수정하지 않아도되고, 또는 다른 단어들에 대한 게으름을 수정할 필요가 없기 때문이다! –

+0

+1 정직! :) – wilx

+0

그냥 앤디가 답변으로 표시했다는 언급 -하지만 이건 내 dev 환경에 맞는 기반으로합니다. 우리가 사용하는 컴파일러 중 하나는 decltype이없는 g ++ 4.2.4입니다. 그러나 당신의 솔루션은 이제부터 문제를 해결할 것입니다. –

관련 문제