将参数包传递给从返回类型中扣除模板的功能

Pass parameter pack to function with template deduction from return type

提问人:Oliver Hawker 提问时间:8/30/2023 更新时间:8/30/2023 访问量:50

问:

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

T result = factoryObject.construct(argA, argB, argC);

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

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);
  }
}

...只要我用:

T result = factoryObject.construct<T>(argA, argB, argC);

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

我尝试使用 operator() 技巧推断类型(根据 https://stackoverflow.com/a/2613010/4649183):

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

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

int main() {
    int p = GC::Allocate();
}

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

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

我能做些什么?

c++ 参数传递 variadic 函数 rvalue-reference

评论

0赞 Enlico 8/30/2023
您是否在代码的第一个片段中缺少一个?return
0赞 NathanOliver 8/30/2023
T 可以变得非常复杂,然后给它一个别名。
1赞 Enlico 8/30/2023
另外,可能是故意的。此外,您还有未扩展的包。此外,在同一范围内转发两次似乎是错误的。std::forward<Args&&>std::forward<Args>args
0赞 Some programmer dude 8/30/2023
由于可能的类型转换,返回类型推导并不是那么简单或总是可能的。
3赞 Some programmer dude 8/30/2023
如果可以很复杂,除了制作别名之外,为什么不使用类型演绎呢?如?Tautoauto result = factoryObject.construct<T_or_alias>(...)

答:

5赞 Jarod42 8/30/2023 #1

你应该拥有所有部分。只需要正确组装它们。代码应类似于:

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)...};
  }
};

评论

0赞 Oliver Hawker 8/30/2023
这太棒了,谢谢!我一知半解这是如何工作的,但已经对其进行了修改,以使用 l 值和 r 值的各种组合对其进行测试,并且效果非常好。我将研究并了解它是如何工作的,但这似乎解决了我的问题。非常感谢您的快速回复!
0赞 Jarod42 8/30/2023
@NathanOliver:已使用左值/右值引用进行修复。Constructor<Args&&...>Ts
0赞 NathanOliver 8/30/2023
啊哈,这就是我所缺少的。