C++ std::function的constexpr版本

C++ std::function的constexpr版本,c++,c++11,metaprogramming,template-meta-programming,constexpr,C++,C++11,Metaprogramming,Template Meta Programming,Constexpr,我正在寻找一个在constexpr中可用的::std::函数。 用例:我有一个函数将函数指针作为参数,第二个函数将lambda传递给第一个函数。这两个都是在编译时完全可执行的,所以我想对它们进行constexpr。 例如: 模板 类constExportFunctionPtr { 私人: 使用Type=typename::std::decay::Type; 常数型函数; 公众: constexpr内联 ConstExportFunctionPtr(const类型f) :功能(f) { } 模板

我正在寻找一个在constexpr中可用的::std::函数。 用例:我有一个函数将函数指针作为参数,第二个函数将lambda传递给第一个函数。这两个都是在编译时完全可执行的,所以我想对它们进行constexpr。 例如:

模板
类constExportFunctionPtr
{
私人:
使用Type=typename::std::decay::Type;
常数型函数;
公众:
constexpr内联
ConstExportFunctionPtr(const类型f)
:功能(f)
{ }
模板
constexpr内联
汽车
运算符()(类型…参数)
常数{
返回函数(args…);
}
};
constexpr内联
无效的
测试()
{
constexpunctionptr测试([](int i)->int{
返回i+1;
});
int i=试验(100);
constexpunctionptr test2([=](int i)->int{
返回i+1;
});
i=试验2(1000);
}
然而,这仅仅是因为我正在将lambda转换为函数指针,当然在捕获lambda时失败了,如第二个示例所示。有谁能给我一些关于如何捕获lambdas的建议吗

这将演示用例:

constexpr
void
walkOverObjects(ObjectList d, ConstexprFunctionPtr<void(Object)> fun) {
// for i in d, execute fun
}

constexpr
void
searchObjectX(ObjectList d) {
walkOverObjects(d, /*lambda that searches X*/);
}
constexpr
无效的
漫游对象(ObjectList d、ConstExportFunctionPtr fun){
//因为我在d,执行乐趣
}
常量表达式
无效的
searchObjectX(对象列表d){
漫游对象(搜索X*/)的d、/*λ;
}
谢谢, 杰克

更新: 感谢您指出C++20解决方案,但是,我想要一个在C++14下工作的解决方案

我正在寻找一个在constexpr中可用的::std::函数

停在这里。这是不可能的
std::function
是一个多态包装函数。无状态lambda、有状态lambda、functor、函数指针、函数引用—所有这些都可以构建有效的
std::function
,在运行时可以更改。因此,使编译时等效只是浪费时间

如果您只需要一个编译时泛型函数参数,那么可以使用模板

template<class functor_type>
class my_generic_function_consumer_class{

   using decayed_function_type = typename std::decay_t<functor_type>;

   decayed_function_type m_functor;

};

因此,C++20改变了很多——最重要的是,您现在可以在
constexpr
上下文中使用动态内存和虚拟函数。这使得完全可以构建std::function的constexpr版本。这是一个概念证明(它很长,没有复制或移动构造函数,所以请不要按原样使用它)。它在Clang10下编译,运行代码。我没有在其他编译器中尝试过,值得注意的是,目前没有一个主要的编译器声称拥有C++-20的完整实现

#包括
#包括
#包括
模板结构函数{
constexpr虚拟Ret运算符()(参数…)const=0;
constexpr virtual~_function()=默认值;
};
模板结构函数impl:public函数{
F;
constexpr Ret运算符()(Args…Args)const覆盖{
返回f(标准::转发(参数)…);
}
constexpr函数的impl(F&&F):F(F){
};
模板结构函数;
模板结构函数{
_函数*real_f{nullptr};
constexpr Ret运算符()(Args…Args)const{
返回实数->运算符()(std::forward(args)…);
}
constexpr~函数(){
如果(实f)删除实f;
}
模板
constexpr函数(F&&F):实函数(新函数)impl(std::move(F)){
};
模板
constexpr Ret call_f_2(const function&f,Args…a){
返回f(标准:正向(a)…);
}
模板
constexpr decltype(自动)调用_f(f&&f,Args&&a){
使用Ret=std::invoke\u result\t;
功能f2=标准::移动(f);
回传呼叫(f2,a…);
}
int main(){
constexpr int c=3;
constexpr int i=call_f([c](int j)constexpr{return c+j;},4);
返回i;
}

您打算如何使用它?为什么不直接使用
autotest=[](inti)->int{returni+1;}?有一种方法可以将捕获的lambda转换为函数指针。@user1095108我知道这种方法,但是,您不能在constexpr中使用它,据我所知,“使编译时等效只是浪费时间。”。我不明白你的意思,
std::variant
“可能”以
constepr
的方式具有相同的参数。
std::function
和其他功能的类型擦除可能会使用与
constepr
不兼容的功能(内存分配、强制转换等),但可能会出现变通/折衷。嗯。。。我对此有点怀疑。将
std::function
本身修改为
constexpr
是没有意义的,因为它可能会有被破坏的风险。但是,对于需要并保证通用可调用包装器在其整个生命周期中引用同一对象(在编译时已知)的情况,有一个很好的理由提供一个等价的
constepr
。您不能创建std::function的constepr版本。时期std::function执行类型擦除,这在constexpr中是不可能的。我感谢您的回答,但我想要一个C++11/14的解决方案,因此我没有将其标记为“正确”的解决方案。但我相信,你的努力会被人们在现代C++版本中寻找解决方案所欣赏。您可能想澄清您的问题以指出这一点——现在它没有提到标准,并且标记为“C++-17”
template<class functor_type>
class my_generic_function_consumer_class{

   using decayed_function_type = typename std::decay_t<functor_type>;

   decayed_function_type m_functor;

};
template<class function_type>
constexpr void walkOverObjects(ObjectList d, function_type&& fun) {
    static_assert(std::is_constructible_v<std::function<void(ObjectList), function_type>>,
                  "function_type given to walkOverObjects is invalid.");
}