C++-为任何lambda创建一个实例化桶

C++ - create a bucket of instantiations for any lambda

本文关键字:一个 实例化 任何 lambda 创建 C++-      更新时间:2023-10-16

我想在一个地方创建几个模板化lambda的实例。每个实例的数量和参数在编译时都是已知的,所以我认为这是可能的。这是我想做的事情的一般说明:

enum class Format
{
FORMAT_1,
FORMAT_2
//, ...
};
template<Format F>
struct SomeData
{
//...
};
template < template<Format> typename Processing >
struct ProcessingForAllFormats
{
Processing<Format::FORMAT_1> processingObject1;
Processing<Format::FORMAT_2> processingObject2;
//...
};
template < template<Format> typename Processing >
decltype(auto) makeProcessingForAllFormats(Processing lambda)
{
//I know this function is completely wrong as
//concrete instantation needs concrete type as an argument
//instead of a template
return ProcessingForAllFormats<Processing>();
}
int main() {
auto processing = makeProcessingForAllFormats(
[](SomeData<auto> data) {/*...*/}
);
return 0;
}

这是我问题的简化图。总之,我想存储任何SomeData对象的处理实例,以备将来使用。我不知道在C++14甚至C++17中是否可能。我知道如果我使用动态多态性而不是静态多态性,这会很容易,但在这种情况下,性能对我来说意义重大。

编辑:

正如TartanLlama所注意到的,使用函子确实更容易实现,但更难使用。我对待FormatSomeDataProcessingForAllFormats就像它是库/API的一部分一样,我希望尽可能多地为该"liblary"的用户提供易用性。Lambdas旨在提供这一点@AndyG的建议很有用——对于lambdas ProcessingForAllFormats,实现必须不同。但我不知道C++14/17中的lambda-模板是否足够强大,可以构建这样的API。

用lambda做这件事听起来很痛苦,因为它不是从模板生成的闭包,而是operator()。有了函子模板,这就容易多了:

enum class Format
{
FORMAT_1,
FORMAT_2
//, ...
};
template<Format F>
struct SomeData
{
//...
};
template < template<Format> typename Processing >
struct ProcessingForAllFormats
{
Processing<Format::FORMAT_1> processingObject1;
Processing<Format::FORMAT_2> processingObject2;
//...
};
template <Format F>
struct Processor {
void operator() (SomeData<F> data) { /*...*/ } 
};
int main() {
auto processing = ProcessingForAllFormats<Processor>{};
}

用限制为所需类型的接口包装泛型lambda如何:

enum class Format
{
FORMAT_1,
FORMAT_2
//, ...
};
template<Format F>
struct SomeData
{
//...
};
template <typename GenericProcessing, Format format>
struct Restrictor
{
Restrictor(GenericProcessing genericProcessingObject)
: genericProcessingObject(genericProcessingObject)
{}
decltype(auto) operator()(SomeData<format> data)
{
return genericProcessingObject(data);
}
private:
GenericProcessing genericProcessingObject;    
};
template <typename GenericProcessing>
struct ProcessingForAllFormats
{
Restrictor<GenericProcessing, Format::FORMAT_1> processingObject1;
Restrictor<GenericProcessing, Format::FORMAT_2> processingObject2;
//...
ProcessingForAllFormats(GenericProcessing genericProcessingObject)
: processingObject1(genericProcessingObject)
, processingObject2(genericProcessingObject)
//...
{}
};
template <typename GenericProcessing>
decltype(auto) makeProcessingForAllFormats(GenericProcessing genericProcessingObject)
{
return ProcessingForAllFormats<GenericProcessing>(genericProcessingObject);
}
int main() {
auto processing = makeProcessingForAllFormats(
[](auto data) {/*...*/});
processing.processingObject1(SomeData<Format::FORMAT_1>{}); // ok
//processing.processingObject1(SomeData<Format::FORMAT_2>{}); // fail by design, expects SomeData<Format::FORMAT_1>
//processing.processingObject2(SomeData<Format::FORMAT_1>{}); // fail by design, expects SomeData<Format::FORMAT_2>
processing.processingObject2(SomeData<Format::FORMAT_2>{}); // ok
}
相关文章: