2016-06-18 2 views
1

한다고 가정에서 유래하기 :베이스는 내가 수업과 같이이

template<class T> 
class Base{ }; 

가정하자 나는 다른 클래스과 같이 있습니다

template<class T, class Other> 
class Derived : 
    public virtual Base<T>, 
    public virtual OtherRandomClass<Other> 
{ }; 

이 버전을 확인하는 템플릿 클래스를 만들 수있는 몇 가지 방법이 있나요 Base (있는 경우) Derived과 같은 임의의 클래스는?

+0

'유도'에 'typedef'를 입력하기 만하면됩니다. –

+0

@ Cheersandhth.-Alf 그건 사실입니다 ....하지만 게으르다. 많은 코드를 다시 작성하고 싶지는 않다. (모두 내 허황이 될지도 모른다.) – DarthRubik

+0

다른 가능한 모든' T '유형. 더 많은 일. –

답변

2

여기에 가능한 해결책이 있습니다 (C++ 11 이후 버전 - 글쎄, C++ 14에서는 작동하지만 에 대해서는 auto 대신 Base<T>을 사용하면 C++ 11에서 사용) :

#include<utility> 
#include<type_traits> 

template<class T> 
class Base{ }; 

template<class T> 
class OtherRandomClass{ }; 

template<class T, class Other> 
class Derived : 
    public virtual Base<T>, 
    public virtual OtherRandomClass<Other> 
{ }; 

template<typename T> 
constexpr auto f(const Base<T> &b) { return b; } 

template<typename T> 
struct S { 
    using type = decltype(f(std::declval<T>())); 
}; 

int main() { 
    static_assert(std::is_same<typename S<Derived<int, double>>::type, Base<int>>::value, "!"); 
} 

DerivedBase에서보다 더 많은 상속 경우가 작동하지 않습니다. 실제로 한 번 Base에서 상속 type에만 T 경우가있다 하나는 심지어 enable_if 비슷하게 작동하는 클래스를 디자인 할 수 있습니다합니다 (void_t 관용구 같은) sfinae를 사용
.

template<typename T> 
constexpr auto f(const Base<T> &b) { return b; } 

template<typename...> 
using void_t = void; 

template<typename T, typename = void_t<>> 
struct S { }; 

template<typename T> 
struct S<T, void_t<decltype(f(std::declval<T>()))>> { 
    using type = decltype(f(std::declval<T>())); 
}; 

이 구조체는 당신이 상상할 수있는 모든 템플릿 속임수에 대한 컴파일시에 사용할 수 있습니다
그것은 다음과 같은 형태를 가질 것이다.

두 경우 모두 S::type (있는 경우)은 Derived이 상속하는 기본 클래스 유형, 즉 Base<T>입니다.
자세한 내용은 예제의 main 기능에서 static_assert을 참조하십시오.

+1

쿨 .... 이것은 정확히 내가 필요로 한 것 !!!!! 나는 데이터를 채취하기 위해 함수를 사용하려고 생각하지 않았다. – DarthRubik

+0

@DarthRubik 사실 꽤 까다 롭다. 나는 그것이 그것을 시험해 볼 때까지 그것이 일할 것이다라고 확신하지 않았다! :-) – skypjack

+1

또한 이상한 세계의'void_t' hack – DarthRubik

1
#include <iostream> 
#include <typeinfo> 

// placeholder template 
template<class SomeDerived> struct traits {}; 

template<class T> 
class Base{ }; 

template<class T> 
class OtherRandomClass{ }; 

template<class T, class Other> 
class Derived : 
    public virtual Base<T>, 
    public virtual OtherRandomClass<Other> 
{ }; 


// specialise for our class to provide introspection 
template< 
    class T1, 
class T2> 
struct traits< 
    Derived<T1, T2> 
    > 
{ 
    using t1_type = T1; 
    using first_base_type = Base<T1>; 
}; 

int main() 
{ 
    Derived<int, float> x; 

    using mytraits = traits<decltype(x)>; 
    std::cout << typeid(mytraits::t1_type).name() << std::endl; 
    std::cout << typeid(mytraits::first_base_type).name() << std::endl; 
} 
+0

와우. 이렇게 쉬운, 나는 그런 복잡한 해결책을 대신 사용했다 !! 유일한 결점은 이것이 'Derived'에 대해서만 작동한다는 것입니다. 또는 적어도, 당신은 기초를 탐지하고자하는 각 클래스에 대한 전문화를 제공해야합니다. OP가 요구 한 것이 확실하지 않습니다. 코멘트에서 그는 그가 다른 클래스를 상속하려고 시도했음을 언급했다. – skypjack

+0

@skypjack 네, 여러분은 인트로 스펙트하고자하는 클래스 (또는 템플릿)의 각 형태에 대한 형질을 생성해야만합니다. 제 느낌은 이런 식의 코드를 자주 접하는 것이 디자인 오류의 결과라는 것입니다. –

+0

물론, 나는 왜 디자인 결정의 배후에 대해 논의하고 싶지 않다. 나는 단지 OP에 답하려고하고있다. 당신의 답변에 감사드립니다. – skypjack

관련 문제