在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的主要:& lt;lambda_f1d2143f356d549800fb3412d8bc61a2>"std:: function<bool(空白)>
现在我可以为lambdas添加另一个构造函数模板
template<typename T, typename UnaryPredicate>
Foo(Value<T> &value, UnaryPredicate predicate) :
Foo(value, function<bool(const Value<T> &)>(predicate))
{
}
,只要传递给该构造函数的lambda有一个Value<T>
参数,它就可以正常工作,但是对于没有参数的lambda,它自然会失败:
Foo fooL0(i, []() { return true; });
所以我可能需要一些SFINAE魔法来为不同的lambdas启用适当的构造函数模板,例如:
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++对所有的实参都是平等的,并试图从所有的实参中推断出你的模板实参。
不能推导所使用的模板实参是错误的,而不仅仅是不一致的推导。它只是不接受那些匹配和"go with It"的。
可以将模板实参标记为非推导式:
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
只从第一个参数推导出来。第2次发生正常转换。
(小的格式更改/优化/代码缩短适用于Foo
, block_deduction
也包括在内)
相关文章:
- 当函数模板参数是具有默认参数的类模板时,函数模板参数的推导如何执行
- 将重载的成员函数传递给函数模板
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 具有常量引用参数的函数模板专用化
- std::span<const T> 作为函数模板中的参数
- 如何编写一个完美的缩写函数模板?
- 仅在函数模板中为那些定义了函数的类型执行函数
- 如何在C++中伪造虚拟可变参数函数模板?
- 以下代码中的函数模板有什么问题?
- 在 C++20 中是否不再允许在 std 中对程序定义类型的函数模板进行专用化?
- 将显式实例化的函数模板与转换匹配
- 使用定义函数模板别名
- 函数模板返回类型
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- C++ std::functional 中的可变参数函数模板
- 单行函数模板 c++ 的内联性保证
- C++函数模板需要 &for 数组参数
- 在c++中传递不同的lambdas给函数模板
- C++使用lambdas对函数模板进行类型擦除