通过返回类型的模板推导将参数包传递给函数

Oli*_*ker -1 c++ parameter-passing variadic-functions rvalue-reference

我正在编写一个对象分配器,我想通过以下方式调用它:

T result = factoryObject.construct(argA, argB, argC);
Run Code Online (Sandbox Code Playgroud)

我目前有这个设计,它有效......

class Factory {
  void* memPool_;
  
  template <typename Tret, typename... Args>
  Tret construct(Args&&... args) {
    Tret::methodA(std::forward<Args&&>(args));
    Tret::Tret(memPool_, std::forward<Args&&>(args);
  }
}
Run Code Online (Sandbox Code Playgroud)

...只要我用以下方式调用它:

T result = factoryObject.construct<T>(argA, argB, argC);
Run Code Online (Sandbox Code Playgroud)

我希望能够在不明确指定的情况下做到这一点TT可能会变得非常复杂,我需要在初始化列表中使用这个工厂内联。我还需要在构造函数初始化列表中使用它,所以我无法调用auto result = factory.construct<T>()(我只需要它根据它正在构造的内容推断返回类型)。

我尝试使用operator()技巧推断类型(根据/sf/answers/182910731/):

public:
    template <class T>
    operator T() { return T(); }
};

class GC {
public:
    static Allocator Allocate() { return Allocator(); }
};

int main() {
    int p = GC::Allocate();
}
Run Code Online (Sandbox Code Playgroud)

...但这不允许我传递参数(因为 operator()不能接受参数)。我尝试将Args&& args元组存储为 的成员,将元组重新打包到参数包中,并使用Tuple to parameter packAllocator问题中提出的逻辑分别调用operator() ,但是

  1. 据我所知,这实际上无法存储对参数的引用(这是有道理的,因为编译器不知道我不会让原始参数超出范围)
  2. 最终的解决方案是如此复杂,以至于我肯定走错了路。

我能做些什么?

Jar*_*d42 5

你应该拥有所有的碎片。只需正确组装它们即可。代码应类似于:

template <typename...Ts>
struct Constructor
{
    Constructor(void* memPool, Ts... args) :
        memPool{memPool},
        args{std::forward<Ts>(args)...}
    {}

    template <typename T>
    operator T() && {
        return std::apply(
            [this](auto&&... args) {
                T::methodA(std::forward<Args&&>(args));
                return T::T(memPool_, std::forward<Args&&>(args);
            },
            args);
    }

    void* memPool_;
    std::tuple<Ts...> args;
};

class Factory {
  void* memPool_;
  
  template <typename... Args>
  Constructor<Args&&...>  construct(Args&&... args) {
      return {memPool_, std::forward<Args>(args)...};
  }
};
Run Code Online (Sandbox Code Playgroud)