2016-07-29 7 views
2

나는 멤버 구조체 SZug 포함 된 템플릿 구조체 SFooC++ : 나는 타입 매개 변수를 다른 구조체 <code>SBar</code>이</p> <pre><code>template <typename tTYPE> struct SFoo { struct SZug {}; }; </code></pre> <p>: 다른 템플릿 클래스의 멤버 형 등 일부 전문 템플릿의 형식 매개 변수는

template <typename tTYPE> 
struct SBar 
    { /* stuff */ }; 

나는 형식 매개 변수에 대한 SZug를 사용하여 SBar 전문과 같이하고 싶습니다 :

template <typename tTYPE> 
struct SBar<typename SFoo<tTYPE>::SZug> 
    { /* different stuff */ }; 

이 컴파일되지 않습니다 - LLVM 출력 :

비 추론 될 템플릿 매개 변수 'tTYPE'는 컴파일러가 쉽게이 원한다면이를 추론 할 수 있지만

, 내가 추측하고있어 그것의 C++ 스펙은이 케이스를 특별히 다룰 필요가 있습니다.

이것을 달성 할 방법이 있습니까?
는 (참고 :. 나는 현재 SFooSZug 외부 이동하고 using 선언을 사용하여 주위에 일하고 있어요,하지만 추한)

+0

이후에 무엇을 할 계획입니까? "전문화"가 무엇을 기대하는지는 분명하지 않습니다. 비 특화되고 전문화 된'SBar' 변수를 선언하는 방법을 보여줄 수 있습니까? – Holt

+0

저는 실제로 이것들을 특성 유형으로 사용하고 있습니다. 따라서 실제로 인스턴스화 된 적이 없습니다. Bar는 단순히 (언급되지 않은) 다른 클래스를위한 constexpr 멤버 포인터를 제공한다. 일반적으로 멤버 포인터는 명시 적으로 지정해야하지만 'SZug'전문화의 경우이를 결정할 수 있습니다. - 궁극적으로 이것은 1 대 N 제네릭 컨테이너에서 N 대 N 일반 임베디드 컨테이너 생성과 관련됩니다. 멤버 포인터는 사용자의 컨테이너 또는 노드 정보 "임베디드"(즉 멤버 변수)를 가리 킵니다. 유형). – xaxazak

+0

나는 그것을 감지하기 위해'SZug'를 약간 수정할 수있다. SFINAE를 사용하여 원하는 것을 쉽게 수행 할 수있다. (내 대답 참조). 그렇게 할 수 없다면,'ttyPE '이'SFoo :: SZug' 클래스라는 것을 알아낼 방법이 있는지 확신하지 못합니다. – Holt

답변

2

나는 완전히 당신이 원하는 것을 이해되지 확신합니다,하지만 당신은 다음 (단지 SZug에 특정 속성을 추가 필요 시도 할 수 :

template <typename tTYPE> 
struct SFoo { 
    struct SZug { 
     // Add this to be able to obtain SFoo<T> from SFoo<T>::SZug 
     using type = tTYPE; 
    }; 
}; 

그런 다음 작은 템플릿 유형 있는지 확인하는

: 유형이 SZug 경우

template <typename tTYPE, typename Enabler = void> 
struct is_SZug: public std::false_type { }; 

template <typename tTYPE> 
struct is_SZug<tTYPE, typename std::enable_if< 
    std::is_same<tTYPE, typename SFoo<typename tTYPE::type>::SZug>{} 
>::type>: public std::true_type { }; 

그리고 "전문성"을 가능하게하는 SBar 템플릿을 약간 수정하십시오 SFoo<T>::SZug입니다

template <typename tTYPE, typename Enabler = void> 
struct SBar 
    { static void g(); }; 

template <typename tTYPE> 
struct SBar<tTYPE, typename std::enable_if<is_SZug<tTYPE>{}>::type> 
    { static void f(); }; 

약간의 검사 :

void f() { 
    SBar<int>::g(); 
    SBar<SFoo<int>::SZug>::f(); 
} 

참고 : 당신은 직접 당신이 단순히 std::is_same 조금의 두 번째 인수를 변경해야, SFoo<T>::SZugtype 속성으로 SFoo<T>을 설정할 수 있습니다.

+0

네,이게 문제를 해결해줍니다, tyvm. 나의 현재의 문제를 위해'using type = tTYPE; '을 추가하는 것은 꽤 간단하다. 'SBar'의 추가 매개 변수는 더 성가 시지만 여전히 수행 할 수 있습니다. 나는 현재 이것이 나의 현재의 수정보다 더 정돈되어 있는지를 결정하고있다. - 더 좋은 대답이 내일까지 도착하지 않으면 나는 이것을 해결 된 것으로 틱 할 것입니다. 건배. – xaxazak

+0

@xaxazak 템플릿에 이러한 Enabler 매개 변수를 추가하는 데 일반적으로 사용되는 관용구입니다 (자동으로 추론해야 함). 그러나 템플릿 템플릿 인수로'SBar'를 사용해야하는 경우 문제가 될 수 있습니다. 어쩌면 왜 짜증나는지 상세히 설명 할 수 있다면 더 적절한 해결책을 제시 할 수있을 것입니다. – Holt

+0

주로 모듈 방식입니다. SBar는 이미 (1 대 N 컨테이너에서) 자주 사용되므로이 새로운 기능 (N 대 N 컨테이너)에 대해 알 필요가 없습니다. 하지만 그것은 내 자신의 코드이므로 업데이트 할 수 있습니다. (SZug는 템플릿 템플릿 매개 변수를 사용하지만) 어디서나 템플릿 템플릿 요소에는 사용되지 않습니다. – xaxazak

1

당신은 (있는 다음을 통해 찾고있는 효과를 얻을 수 있습니다 이는) BTW, 0 1 출력합니다 :

#include <type_traits> 
#include <iostream> 

namespace detail 
{ 
    struct SZugBase{}; 
} 

template <typename tTYPE> 
struct SFoo                                 
{ 
    struct SZug : public detail::SZugBase {}; 
}; 

template<typename tType, bool IsFoo> 
struct SBarBase 
{ 
    int value = 0; 
}; 

template<typename tType> 
struct SBarBase<tType, true> 
{ 
    int value = 1; 
}; 

template <typename tTYPE> 
struct SBar : public SBarBase<tTYPE, std::is_convertible<tTYPE, detail::SZugBase>::value> 
{ /* stuff */ }; 

int main() 
{ 
    SBar<int> b0; 
    SBar<SFoo<int>::SZug> b1; 

    std::cout << b0.value << " " << b1.value << std::endl; 
} 

설명

는 첫째, 우리는 SZug 정규-B 등급을 부여 ASE :

namespace detail 
{ 
    struct SZugBase{}; 
} 

template <typename tTYPE> 
struct SFoo            
{ 
    struct SZug : public detail::SZugBase {}; 
}; 

참고 다음

  1. SZugBase은 아무것도에 의해 파라미터, 그래서 SFoo

  2. SZugBase의 매개 변수에 독립적으로 그것을 참조하기 쉬운에되지

    detail 네임 스페이스이므로 일반적인 C++ 규칙에 따라 클라이언트에 코드를 무시하도록 지시하고 있습니다.

이제 우리는 뭔가 SZug의 비 템플릿 기반에 전환 여부에 전문 SBar 두 개의 기본 클래스, 제공 : 마지막으로

template<typename tType, bool IsFoo> 
struct SBarBase 
{ 
    int value = 0; 
}; 

template<typename tType> 
struct SBarBase<tType, true> 
{ 
    int value = 1; 
}; 

을, 우리는 단지 SBar이 기지의 서브 클래스를 만들 필요가 (전문화에 따라) : 당신이 SBar을 전문으로하지 않는

template <typename tTYPE> 
struct SBar : public SBarBase<tTYPE, std::is_convertible<tTYPE, detail::SZugBase>::value> 
{ /* stuff */ }; 

주를 그녀의 e, 당신은 오히려 기본 클래스를 전문화합니다. 이것은 효과적으로 동일한 효과를 제공합니다.

+0

그것은'SBar > b1;'에서 작동합니다. 불행히도'SBar ::'**'SZug' **'> b1;'(AFAICT는 여전히 0을 출력합니다)을 찾고 있습니다. – xaxazak

+0

@ xaxazak 맞습니다. 질문에서 그 세부 사항을 놓쳤습니다. 그러나 원칙이 적용됩니다. 답변의 세부 사항을 약간 변경하면 원래의 의도에 적용됩니다. 주요 요점은 다음과 같습니다. 1. 템플릿이 아닌 "세부 사항"기본 및 2.이 기본으로 변환 할 수 있는지 여부에 따라 기본 클래스를 전문화합니다. –

+0

그래, 문제가 해결됩니다. 나는 그것을하기에 더 매끄러운 방법일지도 모르는 내 손가락을 횡단하고 있었다. 당신의 솔루션과 홀트 모두 받아 들일 수 있지만 이머 저는 고정자 멤버 타입 (Holt의 메소드)을 추가하는 것이 픽서 구조체로부터 상속하는 것보다 약간 더 멋지다고 생각합니다. – xaxazak