通用创客功能

Generic maker function

提问人:Patrick Wright 提问时间:9/7/2023 更新时间:9/8/2023 访问量:55

问:

我正在尝试编写一个模板函数,该函数通常使用任何给定的“maker”函数创建类型。例如,该函数应该能够创建一个 using 、 或 。intstd::make_uniquestd::make_sharedstd::make_optional

我很确定该解决方案需要使用模板模板。这是我的尝试,但这无法编译。

#include <memory>
#include <optional>

template <template <typename, typename ...> typename Maker>
auto create(int a, int b)
{
    return Maker<int>(a + b);
}

int main()
{
    auto a = create<std::make_optional>(1, 2);
    auto b = create<std::make_unique>(3, 4);
    auto c = create<std::make_shared>(10, 20);
        
    return 0;
}

在这个例子中,我的目的是编写一个函数,给定两个整数,将它们相加并返回一个 、 或 包含两个参数的总和。std::unique_ptr<int>std::shared_ptr<int>std::optional<int>int

C++ 模板 C++17

评论

1赞 Marek R 9/8/2023
std::make_optional不是类型模板。它是功能模板。所以你不能接受它,因为它需要类型模板。create
0赞 pptaszni 9/8/2023
怎么了?auto a = std::make_optional(1 + 2);
0赞 Patrick Wright 9/8/2023
@pptaszni 对我的创建函数进行成像并不像添加两个数字那么简单。我希望它能够使用相同的算法来创建相同的类型,其中包含不同的容器,具体取决于应用程序。
1赞 pptaszni 9/8/2023
嗯,这种调用方式是可以接受的:?auto opt = generate(1, 2, [](auto arg){ return std::make_optional(arg); });
2赞 HolyBlackCat 9/8/2023
够好吗?std::make_optional(foo(a, b))

答:

0赞 463035818_is_not_an_ai 9/8/2023 #1

这三个函数模板都不匹配,因为这是一个类型模板。template <typename, typename ...> typename Maker

函数模板实际上在您可以使用它们执行的操作方面相当有限。

可能是我误解了这个问题。但是,我建议改变你的问题的角度,并编写三个单独的函数,而不是传递函数模板,而是传递用于初始值设定项的操作:std::make_xx

#include <memory>
#include <optional>
#include <functional>

template <typename G>
auto create_optional(int a, int b, G&& g) { return std::make_optional<int>(g(a,b)); }
template <typename G>
auto create_unique(int a, int b, G&& g) { return std::make_unique<int>(g(a,b)); }
template <typename G>
auto create_shared(int a, int b, G&& g) { return std::make_shared(g(a,b)); }


int main()
{
    auto a = create_optional(1,2,std::plus<>{});      // 1+2
    auto b = create_unique(2,3,std::minus<>{});       // 2+3
    auto c = create_shared(3,4,std::multiplies<>{});  // 3+4
}

请注意标准库如何使用类型模板 ,以及应该传递给其他泛型函数的泛型可调用对象。如果要实现初始方法,还可以切换到类型作为模板参数。例如,如注释中建议的那样,传递包装“makers”的 lambda(这样 lambda 的类型就是您的函数模板参数)。plusminusmultiplies