4 Stimmen

Wie kann man zwischen zwei C++-Typen unterscheiden, ohne die Typen zu instanziieren?

Ich habe folgendes Problem:

Ich möchte zwischen zwei Typen bestimmen, ohne die "resultierenden" Typen tatsächlich auszuwerten - da der Typ möglicherweise gar nicht existiert, also ungültig ist. (Bitte kein C++11-Zeug)

Beispiel:

 #include <iostream>
 #include <iterator>

template <bool B, typename T, typename F>
struct TemplateIf {
};

template <typename T, typename F>
struct TemplateIf<true, T, F> {
   typedef T Result;
};

template <typename T, typename F>
struct TemplateIf<false, T, F> {
 typedef F Result;
};

int main(int argc, char** argv)
{

// On GCC this is error as std::iterator_traits<int>::value_type doesn't exist 
typename TemplateIf<true, int, std::iterator_traits<int>::value_type >::Result a;
a = 5;

std::cout << a << std::endl;

 return 0;
}

Kann sie irgendwie bestimmt werden? (Angenommen, der gewählte Typ ist immer gültig, aber der nicht gewählte Typ kann ungültig sein).

4voto

Xeo Punkte 126280

Verwenden Sie eine faule Bewertung:

template<class T>
using Apply = typename T::type;

template<class T>
struct identity{ using type = T; };

template<bool B, class T, class F>
struct lazy_if{ using type = Apply<T>; };

template<class T, class F>
struct lazy_if<false, T, F> : lazy_if<true, F, T>{};

template<class T>
struct lazy_iterator_value_type{
  using type = typename std::iterator_traits<T>::value_type;
};

Live-Beispiel (C++11). Für C++03 ist eine einfache Neufassung erforderlich, um die using-aliases loszuwerden, siehe hier .

4voto

Mankarse Punkte 38418

Anstatt die Typen direkt zu übergeben, übergeben Sie eine Metafunktion, die nach den Typen ausgewertet wird. Diese Metafunktion kann dann innerhalb der if-Anweisung langsam ausgewertet werden.

#include <iostream>
#include <iterator>

template <bool B, typename T, typename F>
struct TemplateIf {};

template <typename T, typename F>
struct TemplateIf<true, T, F> {
    typedef typename T::type Result;
};

template <typename T, typename F>
struct TemplateIf<false, T, F> {
    typedef typename F::type Result;
};

template <typename T>
struct get_value_type {
    typedef typename std::iterator_traits<T>::value_type type;
};

template <typename T>
struct identity {
    typedef T type;
};

int main(int argc, char** argv)
{
    TemplateIf<true, identity<int>, get_value_type<int> >::Result a;
    a = 5;
    std::cout << a << std::endl;
    return 0;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X