C++区分函数对象和值模板参数

4

总的来说,我在理解函子方面遇到了一些困难,因为我对模板编程还比较新。

我的目标是编写一个函数,它接受一个Functor以及一个重载的函数,该函数接受一个值。

理想情况下:

template<typename ValueType>
int function(ValueType v)
{
    v + 1;
    ...
}

template<typename Functor>
int function(Functor f)
{
    f();
    ...
}

我愿意通过将std :: function作为参数之一来承担性能损失,但我特别希望能够将lambda作为参数。
编辑
我想要实现的是在必要时允许我正在构建的结构进行延迟评估:
construct.option(1)
construct.option([](){ return 5;})
construct.value()

使用构造函数选择在调用选项时获取哪个参数的值。(可能需要额外的参数来确定是否选择该选项)

要明确的是,一旦完成此选项调用,它就知道是否评估表达式。

另外,如果参数重载了()运算符,我想调用它,而不管它是否也重载了+1。


2
你可以通过SFINAE(参数是否具有operator())来区分它们。 - geza
2
必须使用重载吗?你的方法存在问题,因为对于 function(x);,目前无法确定应该选择哪个重载。有一些解决方法,但不确定是否值得这样做。你不能将其重命名为 functionTakingValuefunctionTakingFunctor 吗? - 463035818_is_not_a_number
3
顺便提一句,这看起来像是一个 xy问题。你所描述的似乎是你认为解决了我们不知道的问题的解决方案。你实际想要实现什么?也许你可以给出调用该方法的代码示例。 - 463035818_is_not_a_number
4
如果一个参数 x 同时支持 x+1x(),那该怎么办呢?这两者并不是互斥的。这也是为什么有 std::find 用于值类型和 std::find_if 用于函数对象的原因。 - MSalters
2
顺便提一下,如果传递一个值是例外情况,那么也许你可以只有一个接受函数子的函数,并对于你传递的值使用 [](){ return x;}。不确定,但是当启用优化时,我不会期望性能损失很大。 - 463035818_is_not_a_number
显示剩余2条评论
1个回答

6

是的,你可以使用 SFINAE 实现:

// overload taking functor f(int)
template<typename Func>
std::result_of_t<Func(int)>   // or std::invoke_result_t<> (C++17)
function(Func const&func)
{
    return func(0);
}

// overload taking value of builtin arithmetic type
template<typename ValueType>
enable_if_t<std::is_arithmetic<ValueType>::value, ValueType>
function(Value const&val)
{
    return val;
}

4
在C++17中,您可以使用std::is_invocable(_r)来检查函数调用是否可行,这比检查转换为std::function更好。 - Holt
1
@Holt 实际上,即使在C++11中也不需要检查是否转换为std::function - Walter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接