4

我有一个Derived继承自 class 的类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。我当然可以用函数来做到这一点:

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

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

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

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

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

出现错误:

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’

我只是错误地调用了 lambda 吗?还是我必须等待C++20

4

3 回答 3

7

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

(事实上​​,我的 GCC 在诊断中这么说error: lambda templates are only available with -std=c++2a or -std=gnu++2a [-Wpedantic]:)

但是您不必等待 C++20,它已经被带有标志的 GCC 8支持。-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>());

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

于 2018-07-19T16:41:59.697 回答
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() };
 }
于 2018-07-19T17:08:18.467 回答
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>{})
于 2019-02-12T16:02:44.760 回答