没有自动参数的C ++ 17中的模板化lambda

时间:2018-07-19 16:38:33

标签: c++ templates lambda c++17 generic-lambda

我有一个类 <ItemGroup> <BootstrapperFile Include=".NETFramework,Version=v4.0"> <ProductName>Microsoft .NET Framework 4.0</ProductName> </BootstrapperFile> <BootstrapperFile Include="Microsoft.Windows.Installer.4.5"> <ProductName>Windows Installer 4.5</ProductName> </BootstrapperFile> <BootstrapperFile Include="ESRIArcEngine$(EsriVersionLinked)Runtime"> <ProductName>ESRIArcEngine$(EsriVersionLinked)Runtime</ProductName> </BootstrapperFile> <BootstrapperFile Include="SlimDX.January.2012"> <ProductName>SlimDX (January 2012)</ProductName> </BootstrapperFile> </ItemGroup> ,它是从类Derived继承的:

Base<ResourceType>

我想创建一个工厂,该工厂创建类型为template <class ResourceType> class Base { protected: ResourceType* resource; public: void set_resource(ResourceType* resource) { this->resource = resource; } }; template <class ResourceType> class Derived : public Base<ResourceType> { public: using Base<ResourceType>::resource; void print () { std::cout << *resource << std::endl; } }; 的对象。我当然可以用函数来做到这一点:

Derived

但是,我无法为工厂编写lambda函数。如果我使用auto关键字接受模板参数,则可以编写模板化的lambda函数,但是在这里,我只想使用模板来确定返回类型。以下失败:

template <typename ResourceType>
auto derived_factory () { 
  return new Derived<ResourceType>(); 
}

auto derived = *(derived_factory<int>());

出现错误:

auto derived_factory = []<typename ResourceType>() {
  return new Derived<ResourceType>();
};

auto derived = *(derived_factory<int>());

我只是错误地调用了lambda吗?还是我必须等待inherit_unknown_type.cpp: In function ‘int main()’: inherit_unknown_type.cpp:27:36: error: expected primary-expression before ‘int’ auto derived = *(derived_factory<int>()); ^~~ inherit_unknown_type.cpp:27:36: error: expected ‘)’ before ‘int’

3 个答案:

答案 0 :(得分:7)

lambda表达式中的模板参数列表是C++20 feature

(实际上,我的海湾合作委员会在诊断中说:error: lambda templates are only available with -std=c++2a or -std=gnu++2a [-Wpedantic]

但是您不必等待C ++ 20,GCC 8已经supported带有-std=c++2a标志。

您将不得不更改调用语法:您需要derived_factory<int>()来代替derived_factory.operator()<int>()


作为一种替代方案(如果您不想要自由功能),我建议使用变量标签分发:

auto derived_factory = [](auto tag) {
    return new Derived<typename tag::type>();
};

template <typename T> struct tag_type {using type = T;};

// Usage:
derived_factory(tag_type<int>{})

此外,即使您以某种方式进行编译,此行也是如此:

auto derived = *(derived_factory<int>());

无论如何都会导致内存泄漏。为避免这种情况,应将结果存储为指针或引用。甚至更好,请使用智能指针。

答案 1 :(得分:5)

等待C ++ 20,您可以从模板类返回lambda

template <typename ResourceType>
auto make_derived_factory ()
 { return []{ return new Derived<ResourceType>{}; }; }

auto derived = make_derived_factory<int>();

int main ()
 {
   auto df { derived() };
 }

答案 2 :(得分:1)

上面的方法不起作用,但是可以:

auto derived_factory = [](auto tag) 
{
    return new Derived<decltype(tag)::type>();
};

template <typename T> struct tag_type {using type = T;};

// Usage:
derived_factory(tag_type<int>{})