簡體   English   中英

在c ++中將不同的lambdas傳遞給函數模板

[英]Passing different lambdas to function template in c++

我有一個類Foo ,通過它的構造函數接受不同的謂詞變體。

template<typename T>
struct Value
{
    T value;
};

class Foo
{
public:
    template<typename T>
    Foo(Value<T> &value, function<bool()> predicate)
    {
    }

    template<typename T>
    Foo(Value<T> &value, function<bool(const Value<T> &)> predicate) :
        Foo(value, function<bool()>([&value, predicate](){ return predicate(value); }))
    {
    }
};

這允許我用顯式function對象構造類:

Value<int> i;
Foo foo0(i, function<bool()>([]() { return true; }));
Foo foo1(i, function<bool(const Value<int> &)>([](const auto &) { return true; }));

但是在嘗試直接使用lambda時失敗了:

Foo fooL1(i, [](const Value<int> &) { return true; });

由於某種原因我還不了解編譯器沒有考慮在構造函數模板中從lambda到function的隱式轉換的可用性。 錯誤消息是(Visual C ++ 2015,Update 3):

錯誤C2664:'Foo :: Foo(Foo &&)':無法將參數2從'main :: <lambda_f1d2143f356d549800fb3412d8bc61a2>'轉換為'std :: function <bool(void)>'

現在我可以為lambdas添加另一個構造函數模板

template<typename T, typename UnaryPredicate>
Foo(Value<T> &value, UnaryPredicate predicate) :
    Foo(value, function<bool(const Value<T> &)>(predicate))
{
}

只要傳遞給該構造函數的lambda有一個Value<T>參數,它就可以正常工作,但是對於沒有參數的lambdas它自然會失敗:

Foo fooL0(i, []() { return true; });

所以我可能需要一些SFINAE魔法來為不同的lambda啟用適當的構造函數模板,例如:

template<typename T, typename UnaryPredicate,
    typename = enable_if_t<is_callable_without_args> >
Foo(Value<T> &value, UnaryPredicate predicate) :
    Foo(value, function<bool()>(predicate))
{
}

template<typename T, typename UnaryPredicate,
    typename = enable_if_t<is_callable_with_one_arg> >
Foo(Value<T> &value, UnaryPredicate predicate) :
    Foo(value, function<bool(const Value<T> &)>(predicate))
{
}

或者也許只有一個構造函數模板可以做到這一點,例如:

template<typename T, typename UnaryPredicate>
Foo(Value<T> &value, UnaryPredicate predicate) :
    Foo(value, function<???decltype(UnaryPredicate)???>(predicate))
{
}

或者可能是完全不同的解決方案 問題是如何啟用構造函數重載以使用適當的lambdas。

您的問題是C ++平等對待所有參數,並嘗試從所有參數中推斷出您的模板參數。

未能推斷出使用的模板參數是一個錯誤,而不僅僅是不一致的推論。 它只是沒有匹配和“與它一起”的那些。

我們可以將模板參數標記為非推導:

template<class T> struct tag_t {using type=T;};
template<class Tag> using type=typename Tag::type;

template<class T>
using block_deduction = type<tag_t<T>>;

然后:

template<class T>
Foo(
  Value<T> &value,
  block_deduction<function<bool(const Value<T> &)>> predicate
) :
  Foo(
    value,
    [&value, predicate=std::move(predicate)]{ return predicate(value); }
  )
{}

現在T僅從第一個參數推導出來。 第二次正常轉換。

(次要格式更改/優化/代碼縮短適用於您的Foo超出block_deduction也包括在內。)

暫無
暫無

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

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