【发布时间】:2017-03-24 05:22:53
【问题描述】:
我有一个类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,更新 3):
错误 C2664: 'Foo::Foo(Foo &&)': 无法将参数 2 从 'main::' 到 'std::function'
现在我可以为 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 魔法来为不同的 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))
{
}
或者也许是一个完全不同的解决方案?问题是如何使构造函数重载与适当的 lambda 一起工作。
【问题讨论】:
标签: c++ lambda c++14 template-meta-programming sfinae