簡體   English   中英

非捕獲 lambda 和 function 指針作為參數在重載 function 歧義

[英]non-capturing lambda and function pointer as parameter in overloaded function ambiguity

#include <functional>
#include <iostream>

template<typename T>
void test( std::function< void ( const T& ) > f )
{
    T val {};
    f( val );

    std::cout << "std::function" << std::endl;
}

template<typename T>
void test( void(*f) ( const T& ) )
{
    T val {};
    f( val );

    std::cout << "function pointer" << std::endl;
}

int main()
{
    auto capturing_var { 0 };

    // Works because implicit conversion to function pointer isn't applied when lambda is capturing
    test< int >( [ capturing_var ]( const int& x ) { } );

    // Doesn't work because implicitly convertible to function pointer and makes ambiguity
    // I want this line to work somehow, how can i make it worked with same client code ? Is it possible ?
    test< int >( []( const int& x ) { } );

    // This line is finer if it works, but in this case compiler cannot deduce T and also ambiguous if it could
    test( []( const int& x ) { } );

    // Works because of unary + operator so conversion to function ptr and i dont need to specify T
    test( +[]( const int& x ) { } );

    return 0;
}

實際上,我只是希望這段代碼能夠在不更改main()中的任何內容的情況下工作,但我不確定這是否可能。

我可以省略重載的 function ,它采用 function 指針,然后它會起作用,但在這種情況下我需要指定T是什么。

注意:我需要推導出T

您可以使用這個問題中描述的技術和一些小的后處理。

最小的例子:

template<typename Ret, typename Arg>
Arg argument_type(Ret(*)(Arg));

template<typename Ret, typename Fn, typename Arg>
Arg argument_type(Ret(Fn::*)(Arg) const);

template<typename Fn>
auto argument_type(Fn) -> decltype(argument_type(&Fn::operator()));

template<typename Arg, typename Fn>
struct argument {
    static_assert(std::is_invocable_v<Fn, Arg>);
    using type = Arg;
};

template<typename Fn>
struct argument<void, Fn>{
    using type = decltype(argument_type(std::declval<Fn>()));
};

template<typename T = void, typename Fn>
void test(Fn fn) {
    using Arg = std::decay_t<typename argument<T, Fn>::type>;
    std::cout << "Arg = " << boost::typeindex::type_id_with_cvr<Arg>().pretty_name() 
              << std::endl;
}

int main() {
    int capturing_var;

    test<int>([capturing_var](const int& x) {}); // Arg = int
    test<int>([](const int& x) {});              // Arg = int
    test([](const int& x) {});                   // Arg = int 
    test(+[](const int& x) {});                  // Arg = int
    test<int>([](auto x) {});                    // Arg = int
}

如果無法推斷出參數類型,例如,對於可變參數 lambda,則必須提供(最后一個示例)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM