C++ 模板类模板构造函数专门化
我有一个模板类,其成员的类型取决于该类的模板参数。该类有一个模板构造函数。我如何专门化用于确定所述成员类型的类的模板参数的不同情况的构造函数。所讨论的不同类型是具有不同构造函数签名的类,我想在初始值设定项列表中调用成员的构造函数。有解决办法吗?我希望避免使用工厂函数,因为我不想依赖成员的move构造函数来降低成本 编辑: 下面是一个代码示例C++ 模板类模板构造函数专门化,c++,templates,constructor,c++14,specialization,C++,Templates,Constructor,C++14,Specialization,我有一个模板类,其成员的类型取决于该类的模板参数。该类有一个模板构造函数。我如何专门化用于确定所述成员类型的类的模板参数的不同情况的构造函数。所讨论的不同类型是具有不同构造函数签名的类,我想在初始值设定项列表中调用成员的构造函数。有解决办法吗?我希望避免使用工厂函数,因为我不想依赖成员的move构造函数来降低成本 编辑: 下面是一个代码示例 template <typename T, typename C> struct foo { T m; C container; u
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*/)
{}
};
模板
结构foo{
T-m;
C容器;
使用value\u type=typename C::value\u type;
模板
foo(Args&&…Args)
:m(std::forward(args)…),容器(/*此处有不同的内容*/)
{}
};
我的目标是正确初始化
容器
,而不管C
是std::vector
还是std::array
。如果std::is_算术::value==true,我想用全零初始化容器(这就是不同构造函数签名的问题所在)。如果std::is_算术::value==false
,我想默认初始化。如果没有示例,您的问题有点难以理解。我的理解是,您希望专门化类模板的构造函数,并针对不同的模板参数以不同的方式构造其成员。如果这是不正确的,让我知道,我会调整我的答案
同样,如果没有一个例子,你很难知道你在做什么和不理解什么。但一般来说,这与专门化其他方法的方式相同。在头文件中声明所有专门化,并在实现文件中实现它们(除非它们是部分专门化!)。请记住在专门化时使用模板
。以下是一个例子:
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表示算术类型,并默认构造类类型,该语言已经有了这方面的功能
特别是关于它的建设
按照聚合初始化规则初始化数组
然后说这个
如果初始值设定项子句的数量小于成员的数量或初始值设定项列表完全为空,则剩余的成员将值初始化
最后我说了这个
1) 如果T是至少有一个用户提供的任何类型的构造函数的类类型,则调用默认构造函数
4) 否则,对象初始化为零
这允许我们做这个std::array my_array{}代码>和具有十个零或默认构造的T
s。我们也可以做std::vector my_vector(10,T{})
以获得相同的结果(T{}
is value-constructed`)
编辑2:这里有另一个解决方案,它使用[delegating constructor]和标记分派更符合问题的要求
#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;
};
#包括
#包括
#包括
//支持的容器的标记
结构t_标记_数组{};
结构t_标记_向量{};
//标签发送
模板
结构t_容器_标记{};
模板
结构t\u容器\u标签{
使用类型=t_标记_向量;
};
模板
结构t\u容器\u标签{
使用类型=t_标记_数组;
};
//Helper获取std::数组的大小
模板
结构数组大小;
模板
结构数组大小{
静态常数自动值=S;
};
模板
结构foo
{
使用value\u type=typename C::value\u type;
//建造师
模板
foo(Args&&…Args):foo(typename t_container_tag::type{},std::forward(Args)…{}
//向量的特殊构造函数
模板
foo(t_tag_vector&&,Args&&…Args):m(std::forward(Args)…),container(S,value_type{})
//数组的专用构造函数
模板
foo(t_tag_array&&,Args&&…Args):m(std::forward(Args)…),容器{}{}
m型值;
C容器;
};
代码示例可以更深入地描述您的问题。你在找这样的东西吗-?我一有机会就会用你提供的例子编辑我的答案。提示:委托构造函数和标记调度。或者SFINAE,延迟到构造函数实例化(使用额外的伪模板参数)。@bogdan我根据您的提示做了一些研究,并给出了一个示例(非常好的提示!)。我对我的解决方案没有足够的信心将其作为答案发布,但我仍然希望在这个问题的背景下展示它,以获得一些反馈。你能看看我有什么,给我一些反馈吗@bogdan在我发布问题()之前,我已经尝试过sfinae,但是我得到了模板不能重载
@FrançoisAndrieux我认为你应该在你的答案中添加带有委托构造函数的示例,这样其他人也可以看到它,如果pastebin过期。@SU3是的,因为你实际上在尝试重新定义同一个模板。默认模板参数不是模板签名的一部分。您需要更改模板参数或函数参数(甚至函数返回类型)中的某些内容,以便实际声明不同的重载模板。例如:
#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;
};