gpt4 book ai didi

c++ - 在模板构建器模式中排除重复的构造函数调用

转载 作者:IT老高 更新时间:2023-10-28 22:37:24 24 4
gpt4 key购买 nike

考虑以下 builder -like 类,它最终允许我构造一个对象,该对象具有成员变量的某些(运行时)值,以及嵌入由几种(编译时)类型携带的某些行为。

相同的构建允许更新成员变量(通常的构建器模式),以及更改与构建器的类型携带状态相关联的模板 type 参数(仅显示了几个模板类型参数和成员,但实际上会更多):

template <typename T1 = DefaultT1, typename T2 = DefaultT2>
class Builder {
int param1, param2;
Builder(int param1, int param2) : param1{param1}, param2{param2} {}
public:
Builder() : Builder(default1, default2) {}

// methods to change param1 and param2 not shown

/* return a new Builder with T1 changed to the given T1_NEW */
template <typename T1_NEW>
Builder<T1_NEW, T2 > withT1() { return {param1, param2}; }

template <typename T2_NEW>
Builder<T1 , T2_NEW> withT2() { return {param1, param2}; }

Foo make() {
// uses T1 and T2 to populate members of foo
return Foo{ typename T1::member, typename T2::another };
}
};

注意 withT1<>withT2<>允许您为 T1 返回具有不同类型的新构建器的方法或 T2分别。这些方法的主体是相同的:return {param1, param2}; ,实际上比这里显示的要复杂得多(例如,如果有很多参数)。

我想将主体分解成某种构造方法,例如:

template <typename T1_, typename T2_>
Builder<T1_, T2_> copy() { return {param1, param2}; }

然后每个 withT*方法可以只调用copy。

但是,我不清楚如何避免包含 Builder 的完全限定类型在通话中:

template <typename T1_NEW>
Builder<T1_NEW, T2 > withT1() { return copy<T1_NEW, T2>(); }

这里的治疗方法比原来的毒药更糟糕,因为我需要用 <T1_NEW, T2> 来限定每个复制调用(这对于每个 withT* 方法都是不同的)。有什么方法可以引用返回类型或其他类型的扣除,我可以用它来调用 copy()在每个函数中以相同的方式?

我使用 C++11 编写,但也欢迎讨论如何在以后的标准中改进 C++11 解决方案。

最佳答案

我没有 C++11 的解决方案,但正如您自己所说,C++14 可能对其他人有帮助。

如果我理解正确,您需要一个存储任意参数的类,并以一种方便的方式将所有参数传递给构造函数。这可以使用可变模板参数和 std::tuple:

来实现
#include <tuple>

template <typename... Args>
class Builder
{
public:
explicit Builder(Args... args)
: arg_tuple(std::forward<Args>(args)...)
{}

template <typename T>
T make()
{
return std::make_from_tuple<T>(arg_tuple);
}

template <typename T>
Builder<Args..., T> with(T t)
{
return std::make_from_tuple<Builder<Args..., T>>(std::tuple_cat(arg_tuple, std::make_tuple(std::move(t))));
}

private:
std::tuple<Args...> arg_tuple;
};

template <typename... Args>
Builder<Args...> make_builder(Args... args)
{
return Builder<Args...>(std::forward<Args>(args)...);
}

用法:

struct Foo
{
Foo(int x, int y)
: x(x), y(y)
{}
int x;
int y;
};

struct Bar
{
Bar(int x, int y, float a)
: x(x), y(y), a(a)
{}
int x;
int y;
float a;
};

int main()
{
auto b = make_builder().with(5).with(6);
auto foo = b.make<Foo>(); // Returns Foo(5, 6).
auto b2 = b.with(10.f);
auto bar = b2.make<Bar>(); // Returns Bar(5, 6, 10.f).
}

虽然 std::make_from_tuple 是 C++17,但可以使用 C++14 的特性来实现:

namespace detail
{
template <typename T, typename Tuple, std::size_t... I>
constexpr T make_from_tuple_impl(Tuple&& t, std::index_sequence<I...>)
{
return T(std::get<I>(std::forward<Tuple>(t))...);
}
}

template <typename T, typename Tuple>
constexpr T make_from_tuple(Tuple&& t)
{
return detail::make_from_tuple_impl<T>(
std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}

关于c++ - 在模板构建器模式中排除重复的构造函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50539774/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com