2017-05-28 30 views
6
template<typename T> struct S {}; 
template<typename T> struct R {}; 

int main() { 
    typedef S<double> s1; 
    typedef S<int> s2; 
    typedef R<int> s3; 
    static_assert(xxx<s1, s2>::value, 
       "No, assertion must not be raised"); 
    static_assert(xxx<s2, s3>::value, 
       "Yes, assertion must be raised"); 
} 

Tak, chcę xxx<s1, s2>::value wrócić prawda podczas xxx<s2, s3>::value do return false podczas kompilacji.uzyskać oryginalną nazwę struct/klasy C++ szablonu podczas konkretyzacji

Czy istnienie xxx jest niemożliwe w C++? Czy istnienie xxx jest teoretycznie możliwe w C++, ale prawdopodobnie nikt tego jeszcze nie zrobił?

+0

Więc 'xxx :: wartość' to 'prawda' iff' T' i 'U' to specjalizacje tego samego szablonu? – Quentin

+0

@Quentin: tak :) –

Odpowiedz

5

Zastosowanie dwie specjalizacje, które używają parametrów szablonu szablon do wykonywania tego „dopasowanie”:

template< 
    typename T, 
    typename V> 
struct xxx; 

template< 
template <class> class A, 
template <class> class B, 
typename X, 
typename Y> 
struct xxx<A<X>, B<Y>> { 
    static constexpr const int value = false; 
}; 


template< 
template <class> class U, 
typename X, 
typename Y> 
struct xxx<U<X>, U<Y>> { 
    static constexpr const int value = true; 
}; 

With your code on ideone

Uwaga: aby była ona prawdziwą cechę typu nie należy ustawić value ręcznie, ale pochodzą z std::integral_constant (std::true_type lub std::false_type). Powyżej jest tylko szybka makieta, którą zrobiłem na moim telefonie.

+0

Co to jest * constexpr const *? –

+1

Czy jesteś pewien, że potrzebujesz _dwóch specjalizacji? –

+0

@HWalters Nie, ale w dwóch specjalizacjach daje błąd, jeśli był używany z typami, które nie są instancjami niektórych szablonów. Wolałbym to w ten sposób, ponieważ teraz ta cecha robi tylko * jedną * rzecz (te same szablony?), A nie dwie (szablony - te same szablony?). –

1

Coś same_base_template:

#include <type_traits> 
template<class A, class B> 
struct same_base_template : std::false_type{}; 

template<template<class...> class S, class... U, class... V> 
struct same_base_template<S<U...>, S<V...>> : std::true_type{}; 

Edit:

I trzecia specjalizacja ponieważ używasz non typu argumenty szablonu (std::ratio):

template<class T, template<T...> class S, T... U, T... V> 
struct same_base_template<S<U...>, S<V...>> : std::true_type{}; 

Demo

To używa true_type i false_type od type_traits, więc nie musimy sami pisać constexpr bool value. Użyłem tutaj szablonu variadic, ponieważ był nieco bardziej ogólny i wykonał tylko kilka kolejnych naciśnięć klawiszy. Dla twojego konkretnego zastosowania, nie potrzebujesz ich)

+0

Jestem uszy dla lepszego imienia niż 'same_base_template'. – AndyG

+0

Kiedy używam 'ten sam_base_template' w następujący sposób, najpierw uwzględniając nagłówek' ratio': 'int main() {typedef std :: ratio <7, 8> r1; typedef std :: ratio <12, 9> r2; static_assert (same_base_template :: value, "Nie, asercja nie zostanie podniesiona"); } ', kompilując go za pomocą' g ++ -std = C++ 14 -o mwe mwe.cpp' podnosi asercję statyczną 'error: asercja statyczna nie powiodła się: Nie, asercja nie zostanie podniesiona', co nie powinno mieć miejsca. Dowolny pomysł? –

+0

@TadeusPrastowo: Dzieje się tak, ponieważ 'std :: ratio' akceptuje argumenty szablonu non-type (liczby całkowite dla współczynnika). To trochę różni się od tego, czego się spodziewałem, więc dodałem kolejną specjalizację. Zaktualizowałem swój post. Zobacz nową wersję demonstracyjną. – AndyG