Frage

Was ist mit dem folgenden Ausschnitt falsch?

#include <tr1/functional>
#include <functional>
#include <iostream>

using namespace std::tr1::placeholders;

struct abc
{
    typedef void result_type;

    void hello(int)
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    void hello(int) const
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    abc()
    {}
};

int
main(int argc, char *argv[])
{
    const abc x;
    int a = 1;

    std::tr1::bind(&abc::hello, x , _1)(a);
    return 0;
}

Der Versuch, es mit g ++ zu kompilieren - 4.3, scheint es, dass cv -qualifier ladenen Funktionen verwirren sowohl tr1::mem_fn<> und tr1::bind<> und es kommt folgende Fehlermeldung:

no matching function for call to ‘bind(<unresolved overloaded function type>,...

Stattdessen wird der folgende Code-Schnipsel kompiliert aber scheint die const-Korrektheit zu brechen :

struct abc
{
    typedef void result_type;

    void operator()(int)
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    void operator()(int) const
    { std::cout << __PRETTY_FUNCTION__ << std::endl; }

    abc()
    {}
};

...

    const abc x;
    int a = 1;
    std::tr1::bind( x , _1)(a);

Jeder Hinweis?

War es hilfreich?

Lösung

Das Nachschlagen zu einem Zeitpunkt durchgeführt, wenn die Konstantheit von this ist nicht bekannt. Sie müssen es nur einen Hinweis über Gießen geben. Versuchen Sie folgendes:

typedef void (abc::*fptr)(int) const; // or remove const
std::tr1::bind((fptr)&abc::hello, x , _1)(a);

Sie können auch hier feststellen, dass die const Entfernung noch funktioniert. Dies liegt daran, dass man x sollte durch Zeiger Passing (weil das erste Argument für eine C ++ Elementfunktion, der implizite this Parameter ist immer ein Zeiger). Versuchen Sie stattdessen:

typedef void (abc::*fptr)(int) const; // won't compile without const (good!)
std::tr1::bind((fptr)&abc::hello, &x , _1)(a);

Wie unten während innerhalb von mir entdeckt, wenn Sie die & weglassen, wie Sie ursprünglich tat, werden Sie x werden vorbei Wert , das ist in der Regel nicht, was Sie wollen (obwohl es wenig praktikabel macht Unterschied in Ihrem speziellen Beispiel). Dies scheint tatsächlich wie ein unglücklicher pitfall für bind.

Andere Tipps

Diese Frage beantwortet wurde, aber ich finde den besten Weg, um eine Überlastung zu spezifizieren mit binden sie auf der Vorlage angeben, lautet:

std::tr1::bind<void(foo::*)(int)>(&foo::bar);

Diese Methode ist ebenso explizit, aber kürzer als Gussteil (mit static_cast sowieso. Aber es ist sauberer als das C-Cast, die gleich lang ist.

Wie John vorgeschlagen, die in diesen Schnipsel entstanden Probleme sind die folgenden:

  1. Beim Passieren eines Mitglied-Funktion-Zeiger ist es notwendig, seine Unterschrift zu geben (wenn überlastet)
  2. bind() werden gebenen Argumente von Wert.

Das erste Problem ist durch Gießen des Mitgliedsfunktionszeigers vorgesehen gelöst zu binden:

    std::tr1::bind(static_cast< void(abc::*)(int) const >(&abc::hello), x, _1)(a);

Die zweite kann, indem man das aufrufbare Objekt nach Adresse gelöst werden (als John vorgeschlagen) oder mittels TR1 reference_wrapper<> - sonst wird es von Wert übergeben werden, so dass die const-Korrektheit bricht Halluzination .

x ein aufrufbare Objekt Gegeben:

std::tr1::bind( std::tr1::ref(x) , _1)(a);

bind() wird a auf die richtige operator() gemäß der x weiterleiten Konstantheit .

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