gpt4 book ai didi

c++ - 模板类模板构造函数特化

转载 作者:搜寻专家 更新时间:2023-10-31 01:33:25 24 4
gpt4 key购买 nike

我有一个模板类,其成员的类型取决于类的模板参数。该类有一个模板构造函数。我如何针对确定所述成员类型的类模板参数的不同情况专门化构造函数。所讨论的不同类型是具有不同构造函数签名的类,我想在初始化列表中调用成员的构造函数。有解决方法吗?我想避免诉诸工厂函数,因为我不想依赖便宜的成员移动构造函数。

编辑:这是一个代码示例,

template <typename T, typename C>
struct foo {
T m;
C container;
using value_type = typename C::value_type;

template <typename... Args>
foo(Args&&... args)
: m(std::forward<Args>(args)...), container(/*different stuff here*/)
{}
};

我的目标是正确初始化 container不管是否Cstd::vectorstd::array .如果std::is_arithmetic<value_type>::value==true ,我想用全零初始化容器(这是不同构造函数签名的问题所在)。如果std::is_arithmetic<value_type>::value==false , 我想默认初始化。

最佳答案

如果没有示例,您的问题有点难以理解。我对它的理解是,您想专门化类模板的构造函数,并为不同的模板参数构造不同的成员。如果这不正确,请告诉我,我会调整我的答案。

再一次没有例子,很难知道你做了什么,不明白。但一般来说,这与您专门化其他方法的方式相同。在您的 header 中声明所有特化并在您的实现文件中实现它们(除非它们是部分特化!)。记得用 template<>专精的时候。这是一个例子:

struct t_param_for_int {};
struct t_param_for_double {};


// t_member's constructor is very different depending on T
template<class T> struct t_member {};

template<> struct t_member<int> {
explicit t_member(const t_param_for_int value) {};
};

template<> struct t_member<double> {
explicit t_member(const t_param_for_double value) {};
};

// Foo has a t_member and a constructor
template<class T>
struct foo
{
foo();

t_member<T> member;
};

// Declare specialization
template<> foo<int>::foo();
template<> foo<double>::foo();

// Specialization implementations (in a .cpp)
template<> foo<int>::foo() : member(t_param_for_int{})
{ }

// Specialization implementations (in a .cpp)
template<> foo<double>::foo() : member(t_param_for_double{})
{ }

int main()
{
foo<int> int_foo;
foo<double> dbl_foo;
return 0;
}

编辑:响应对问题的编辑。

在这种情况下你不能特化一个构造函数。最好的解决方案可能是使用辅助结构来进行实际的初始化。你提到你想用一些 0 或默认构造的元素来初始化你的容器 T .但是你没有指定你的容器应该有多大。我构建了一个示例来说明使用假容器大小使用辅助结构的解决方案。

#include <array>
#include <iostream>
#include <type_traits>
#include <string>
#include <utility>
#include <vector>

template<typename T, typename C>
struct helper_init;

template<typename T>
struct helper_init<T, std::vector<T>> {
static std::vector<T> init() {
return std::vector<T>(3, T{}); // init your vector with 3 elements
}
};

template<typename T>
struct helper_init<T, std::array<T, 2>> {
static std::array<T, 2> init() {
return {}; // init your array with 2 elements
}
};

template <typename T, typename C>
struct foo {
T m;
C container;
using value_type = typename C::value_type;

template <typename... Args>
foo(Args&&... args)
: m(std::forward<Args>(args)...)
, container(helper_init<T, C>::init())
{}
};

int main()
{
foo<int, std::vector<int>> vec_foo(5);
foo<std::string, std::array<std::string, 2>> str_foo("hello");

// Output to illustrate

// The size of the containers are 3 and 2 (see container initialization)
std::cout << vec_foo.container.size() << ' '
<< str_foo.container.size() << std::endl;

// The m members contain the assigned values
std::cout << vec_foo.m << " \'" << str_foo.m << '\'' << std::endl;

// The containers are zero or default initialized
std::cout << vec_foo.container.front() << " \'" <<
str_foo.container.front() << '\'' << std::endl;
return 0;
}

对于问题的第二部分,将 0 初始化为算术类型和类类型的默认构造,该语言已经具有此功能。

std::array特别说明了它的结构。

initialized the array following the rules of aggregate initialization

然后 aggregate initialization这么说。

If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized.

最后value initialization这么说。

1) if T is a class type with at least one user-provided constructor of any kind, the default constructor is called;

4) otherwise, the object is zero-initialized.

这使我们能够做到这一点 std::array<T, 10> my_array{};并有十个归零或默认构造T秒。我们也可以做 std::vector<T> my_vector(10, T{});得到相同的结果(T{} 是构造值`)。

编辑 2:这是另一个使用 [委托(delegate)构造函数] 和标签调度更符合问题要求的解决方案。

#include <array>
#include <string>
#include <vector>


// Tags for supported containers
struct t_tag_array {};
struct t_tag_vector {};

// Tag dispatching
template<class T, size_t S>
struct t_container_tag {};

template<class T, size_t S>
struct t_container_tag<std::vector<T>, S> {
using type = t_tag_vector;
};

template<class T, size_t S>
struct t_container_tag<std::array<T, S>, S> {
using type = t_tag_array;
};

// Helper to fetch the size of an std::array
template<typename>
struct array_size;

template<typename T, size_t S>
struct array_size<std::array<T, S>> {
static const auto value = S;
};

template <typename C, size_t S = array_size<C>::value>
struct foo
{
using value_type = typename C::value_type;

// Constructor
template<typename... Args>
foo(Args&&... args) : foo(typename t_container_tag<C, S>::type{}, std::forward<Args>(args)...) {}

// Specialized constructor for vectors
template<typename... Args>
foo(t_tag_vector &&, Args&&... args) : m(std::forward<Args>(args)...), container(S, value_type{}) {}

// Specialized constructor for arrays
template<typename... Args>
foo(t_tag_array &&, Args&&... args) : m(std::forward<Args>(args)...), container{} {}

value_type m;
C container;
};

关于c++ - 模板类模板构造函数特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41473675/

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