Frage

Ich schreibe eine Funktor F der Funktion vom Typ void nimmt (* func) (T) und das Argument ARG func.

template<typename T>
  void F(void (*func)(T), WhatTypeHere? arg)
{
  func(arg);
}

Dann Funktor F ruft func mit ARG. Ich möchte F nicht arg kopieren, nur um es als Referenz zu übergeben. Aber dann kann ich nicht einfach schreiben "Leere F (void (* func) (T), T &)", weil T könnte ein Hinweis sein. Also versuche ich, einen Zug zu schreiben, die richtigen Referenz-Typen von T erhalten kann:

T -> T&
T& -> T&
const T -> const T&
const T& -> const T&

ich kommen mit etwas wie folgt aus:

template<typename T>
 struct type_op
{
 typedef T& valid_ref_type;
};

template<typename T>
 struct type_op<T&>
{
 typedef typename type_op<T>::valid_ref_type valid_ref_type;
};

template<typename T>
 struct type_op<const T>
{
 typedef const T& valid_ref_type;
};

template<typename T>
 struct type_op<const T&>
{
 typedef const T& valid_ref_type;
};


template<typename T>
  void F(void (*func)(T), typename type_op<T>::valid_ref_type arg)
{
  func(arg);
}

Was nicht Arbeit zum Beispiel tut für

void a(int x) { std::cout << x << std::endl; }
F(&a, 7);

Geben Fehler:     invalid Initialisierung nicht const Referenz vom Typ 'int &' von einem temporären des Typs 'int' in Übergabe des Arguments 2 von 'VOID F (void (*) (T), typename type_op :: valid_ref_type) [mit T = int]'

Wie dieses Merkmal zur Arbeit kommen?

War es hilfreich?

Lösung

template<class T>
struct forwarding { typedef T const& type; };
template<class T>
struct forwarding<T&> { typedef T& type; };

template<typename T>
void F(void (*func)(T), typename forwarding<T>::type arg) {
  func(arg);
}

void a(int x) { std::cout << x << std::endl; }
int main() {
  F(&a, 7);
}

Ihre Zuordnung war in der Nähe, die Sie tatsächlich wollen T auf T const abgebildet und auch:

T        -> T const&
T&       -> T&
T const& -> T const&

Beachten Sie, dass Funktionen einen Parametertyp von T const eine Signatur von T haben! Die const ist eine Implementierung Detail:

void f(int const);
typedef void F(int); // typedef of function type
F* p = &f; // no error! f's signature doesn't include const

Andere Tipps

Alles, was Sie brauchen, ist eine Referenz zu entfernen:

template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };

Sie es dann erneut hinzufügen wie folgt:

remove_reference<T>::type&

sollte Ihre Funktion wie folgt deklariert werden:

template<typename T>
void F( void (*func)(T), const typename remove_reference<T>::type& arg )
{
  func(arg);
}

Es ist ein bisschen vage in meinem Kopf, aber ich denke, dass Boost (vielleicht boost :: bind) löst dieses Problem, indem nur const T& Züge bereitstellt, und die die Verwendung von ref(x) eine nicht konstanter Referenz anzuzeigen.

Sie können auch eine href verwenden <= "http://www.boost.org/doc/libs/1_41_0/libs/type_traits/doc/html/boost_typetraits/reference/add_reference.html" rel = "nofollow noreferrer" > add_reference von Boost.TypeTraits den Typ-Mapping müssen Sie zu erreichen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top