2016-11-29 12 views
8

"Practical C++ Metaprogramming" adlı kitabı okudum ve derleyemediğim aşağıdaki örneğe sahibim. Bunu benim için halledebilir misin?Pratik C++ Metaprogramlama

template <typename F> 
struct make_tuple_of_params; 

template <typename Ret, typename... Args> 
struct make_tuple_of_params<Ret (Args...)> 
{ 
    using type = std::tuple<Args...>; 
}; 

template <typename F> 
using make_tuple_of_params_t = typename make_tuple_of_params<F>::type; 

template<typename F> 
void some_magic_function(F callable) 
{ 
    make_tuple_of_params_t<F> tuple; 
    /* 
    ... do something with arguments in tuple... 
    */ 
} 

int main() 
{ 
    some_magic_function([] (int, double, float) {}); 
} 

Dediğim bir derleme hatası alıyorum: 'type' 'make_tuple_of_params' herhangi bir doğrudan veya dolaylı taban sınıfın bir üyesi değildir. Varsayılan yapı seçildiğinden beri SFINAE beklendiği gibi çalışmıyor gibi dikişler. Bunu nasıl düzeltirim?

+0

Bir lambda tipi bir işlev türü değil. – aschepler

+1

C++ 14'deki lambdaların, otomatik olarak parametreli olarak algılanabilen "auto" parametrelerine sahip olabileceğini unutmayın. Bu tür lambdalar için, tuple tipinizin benzer görünmesini ne bekliyorsunuz? –

+2

Yukarıdaki SFINAE yok, sadece – Yakk

cevap

5

:

#include <tuple> 
#include <typeinfo> 
#include <iostream> 

template <class> 
struct make_tuple_of_params; 

template <class Res, class Type, class... Args> 
struct make_tuple_of_params<Res (Type::*)(Args...) const> { 
    using type = std::tuple<Args...>; 
}; 

template <class F> 
using make_tuple_of_params_t = typename make_tuple_of_params<F>::type; 

template<typename F> 
void some_magic_function(F callable) 
{ 
    make_tuple_of_params_t<decltype(&F::operator())> tuple; 
    std::cout << typeid(tuple).name() << std::endl; 
} 

int main() 
{ 
    some_magic_function([] (int, double, float) {}); 
} 

[live demo]

6

[] (int, double, float) {} türü, main için yerel adı verilen ve kapanış türü olarak adlandırılan adsız bir sınıf türüdür. Kesinlikle void (int, double, float); aslında bir işlev türü değil. Bu nedenle, işlev türleri için uzmanlık geçerli değildir ve birincil şablon seçilir. (Kodunuzda SFINAE bulunmadığını unutmayın).

Bunu nasıl düzelteceğinize gelince: Tamamen genel bir çözüm olduğunu düşünmüyorum. Belirli bir some_magic_function için bir çözüm/geçici çözüm olabilir, ancak bu, yapmanız gereken işleve bağlı olarak değişir. aşağıdaki gibi görünebilir oto parametreleri ile Lambda'lar geçici çözüm dahil değilse lambdas için

+1

ile eşleşen uzmanlık şablon şablonu: Potansiyel düzeltmelerle ilgili olarak: lambda'yı '+ [] (int, double, float) {}' ile bir işlev göstericisine dönüştürmek, hiçbir şeyin yakalanması gerekmediğinde bir seçenek olabilir. Elbette, make_tuple_of_params', işlev işaretçileri ve işlev türleri ile eşleşmelidir. –

+0

Tamam Bir işlev işaretçisi ile denedim ama başarılı olmadı. – 0xBADF00

+0

@ 0xBADF00 Bu, Markus'un yorumunun ikinci cümlesi kapsamındadır. – Yakk

İlgili konular