2011-05-31 26 views
7

Olası çoğaltmaları:
Why can't my C++ compiler deduce template argument for boost function?
Isn't the template argument (the signature) of std::function part of its type?Örtülü dönüşümler :: fonksiyon

Ben şu var:

#include <functional> 

void Foo(std::function<void()> ); 
void Foo(std::function<void(int)>); 
void Bar(); 

int main() 
{ 
    Foo(Bar);  // Error: ambiguous 
    Foo([](){}); // Error: ambiguous 

    Foo(std::function<void()>(Bar )); // Ok 
    Foo(std::function<void()>([](){})); // Ok 
} 

İlk iki satır yapabilir main() işlev stili casussuz çalışır Son iki satırda t? Belki bir std :: enable_if çözümü ile?

cevap

4

herhangi arama tam olarak çözülmemiş aşırı yüklenme neden olur std::function<void()> biri ve std::function<void(int)> olmayan bir parametre ile fan olarak. Hatta Foo(1) veya Foo("abc") gibi aptalca şeyler. Bunun nedeni, std::function kurucularının tempoldedilmesi ve herhangi bir türü kabul etmesidir. std::function<void()>(1), örneklemede başarısız olur, ancak aşırı çözünürlük, örneklemeden önce gerçekleşir.

Hayır, işlevlerden birine tam olarak bir eşleşme sağlamanız gerekir. Sen

void Foo(void (*)()); 
void Foo(void (*)(int)); 

gibi, Foo diğer aşırı örneklerini tanıtmak olabilir ve bu daha iyi bir eşleşme getirir ve belirsizlik fazla olmayacaktır.

3

Bu işi düzgün yapmak için SFINAE'yi C++ 0x'de kullanmak mümkündür. Ancak, MSVC'nin SFINAE hataları bildiğim kadarıyla onları imkansız kılıyor ve GCC'nin kütüphane uygulayıcıları farketmiş gibi görünmüyor, bu yüzden maalesef işe yaramıyor.

Ayrıca bir çeşit make_function deneyebilirsiniz, sanırım. Variadic şablonlarımdan özür dilerim, bir süredir.

template<typename T> struct function_proxy { 
    T f; 
    template<typename Ret, typename... T> operator std::enable_if<std::is_same<Ret, decltype(f(std::declval<T>()...))>::value, std::function<Ret(T...)>>::type() { 
     return std::function<Ret(T...)>(f); 
    } 
}; 
template<typename T> function_proxy<T> make_function(T&& t) { 
    return function_proxy { std::forward<T>(t); } 
}