2016-06-19 10 views
0
template <typename Function> 
struct function_traits 
    : public function_traits<decltype(&Function::operator())> { 
}; //1 why function_traints inherit from itself? 

template <typename ClassType, typename ReturnType, typename... Args> 
struct function_traits<ReturnType(ClassType::*)(Args...) const> { 
    typedef ReturnType (*pointer)(Args...); 
    typedef std::function<ReturnType(Args...)> function; 
}; //2 this class do nothing just typedef type ? 

template <typename Function> 
typename function_traits<Function>::function 
to_function (Function & lambda) { 
    return static_cast<typename function_traits<Function>::function>(lambda); 
} 

template <typename Lambda> 
size_t getAddress(Lambda lambda) { 
    auto function = new decltype(to_function(lambda))(to_function(lambda)); 
    //3 func is std::function pointer,this conversion is ok? 
    void * func = static_cast<void *>(function); 
    return (size_t)func; 
} 

int f(int, int) { return 1; } 
int g(int, int) { return 2; } 
std::function<int(int, int)> lambda1 = [](int a, int b)->int 
{ 
    return 1; 
}; 
std::function<int(int, int)> lambda2 = [](int a, int b)->int 
{ 
    return 1; 
}; 

void test(std::function<int(int, int)> const& arg,const char* info) 
{ 
    std::cout << "test function: "; 
    std::cout << (void*)getAddress(arg) << " " << info << std::endl; 
} 

int main() 
{ 
    test(lambda1,"lambda1"); 
    test(lambda1,"lambda1"); 
    test(lambda2,"lambda2"); 
    test(lambda2,"lambda2"); 
    test(std::function<int(int, int)>(std::plus<int>()),"plus"); 
    test(std::function<int(int, int)>(std::minus<int>()),"minus"); 
    test(std::function<int(int, int)>(f),"f"); 
    test(std::function<int(int, int)>(g),"g"); 
} 

1 warum Funktionstraints von sich erben?C++ Vorlagencode erklären

ich weiß, dass dies seltsam wiederkehrende Vorlage Muster ist. die function_traints während kompilieren zu zwei verschiedenen Klassen.

2 die zweite Klasse nichts tun nur Typdef Typ?

ja, nur für die bequeme

3 func ist std :: Funktionszeiger, ist diese Umwandlung ok?

[TODO]

4 die Hauptfunktion Ergebnis ist:

test function: 0x7f9440407f50 lambda1 
test function: 0x7f9440407f80 lambda1 
test function: 0x7f9440407fb0 lambda2 
test function: 0x7f9440407fe0 lambda2 
test function: 0x7f9440408010 plus 
test function: 0x7f9440408040 minus 
test function: 0x7f9440408070 f 
test function: 0x7f94404080a0 g 

diese Funktion oben ist falsch? Ich kann es nicht verwenden, um zu überprüfen, ob zwei Funktionen gleich sind.

[TODO]

Können Sie den Code oben erklären? Vielen Dank!

+0

"Ich weiß, das ist seltsam wiederkehrende Vorlage Muster" - Dies ist nicht CRTP. – SChepurin

Antwort

1

Warum vererbt function_traints von sich selbst?

Es tut es nicht. Function und decltype(&Function::operator()) sind verschiedene Typen, also function_traits<Function> und `function_traits sind auch unterschiedliche und nicht verwandte Typen.

die zweite Klasse tun nichts nur Typdef Typ?

Ja. Dies ist normal für eine Merkmalsklasse. In diesem Fall bietet function_traits einen eindeutigen Zugriff auf den Rückgabetyp eines aufrufbaren Objekts, unabhängig davon, was dieses Objekt ist: ein Funktionszeiger, ein Zeiger auf Element, ein Lambda oder irgendetwas anderes.

func ist std :: funktion zeiger, diese umwandlung ist ok?

Nein, die Konvertierung ist nicht OK. Es gibt mindestens drei Probleme damit:

  1. Sie können nicht nur jedes Lambda in einen Funktionszeiger konvertieren, nur nicht erfassende Lambdas.
  2. Es gibt ein Speicherleck (die dynamische Zuweisung ist völlig unnötig).
  3. Ein Funktionszeiger ist im Allgemeinen nicht kompatibel mit void* und void* ist nicht kompatibel mit size_t. Dieser Code funktioniert möglicherweise auf einigen Plattformen, aber nicht auf anderen Plattformen.
+0

vielen dank! Es gibt noch einen weiteren Zweifel:
func ist std :: function Zeiger, diese Konvertierung ist in Ordnung?
bitte erklären Sie den static_cast. Danke!^V^ – wolfand11

+0

oh. Aha. Danke noch einmal!^V ^ – wolfand11