我想要创建一个模板,其参数B和D是模板实例化中固定数组的基类和元素:
template <class B,class D>
struct fix_array : public B {
D myArray[5];
/**/ fix_array( void ) { cout << "completely default constructed"; }
};这个很好用。接下来,我想将初始化值传递给B:
template <class... BI>
/**/ fix_array( BI &&... bi )
: B( std::forward<BI>(bi)... )
, myArray( )
{ cout << "This works too, even for multi-argument constructors of B."; }这也很管用。最后,我的问题是:
如何通过模板构造函数将初始化值传递给D myArray[5]; ?
我设想调用代码的样子如下:
fix_array<B,D> myVal( { B-initializers }, { { D[0]-initializers }, { D[1]-initializers } } );但我迷失在各种模板的地狱里。是否所有的D初始化器都必须具有相同的形式?(假设D可以使用int、const char *或D &&初始化。)
这是我的测试程序。debug-util.hh定义了一个类Vobject,它在构造、销毁、复制信息时输出信息。
#include <stdio.h>
#include <memory.h>
#include <iostream>
#include <typeinfo>
#include <memory>
#include <vector>
#include "debug-util.hh" // Defines Vobject and some other info-printing utilities
template <class B, class T>
class fix_array : public B
{
public:
T pData[5];
/**/ fix_array( void ) : B( ), pData( ) { std::cerr << "completely default construction" << std::endl; }
template <class... BI>
/**/ fix_array( BI &&... bi )
: B( std::forward<BI>(bi)... )
, pData( )
{
std::cerr << "fix_array Base was initialized" << std:: endl;
}
} ;
/*
* A Vobject has 4 constructors: (void), (int), (int,char*), (int,int,int)
*
* It prints information about how it's constructed, when it's copied or moved,
* and when it's destroyed.
*/
int
main( int, char ** )
{
fix_array<Vobject,Vobject> a; // These 4 initialize the Base Vobject
fix_array<Vobject,Vobject> b( 1 ); // using the various constructors.
fix_array<Vobject,Vobject> c( 3, "foobar" );
fix_array<Vobject,Vobject> d( 100, 200, 300 );
// HOW CAN I PASS INITIALIZERS TO THE pDATA ARRAY MEMBERS???
// fix_array<Vobject,Vobject> x( { 123, "base init" }, { { 1 }, { 2, "xyz" }, { 2, 4, 5 } } );
std::cerr << "Hello, world" << std::endl;
return 0;
}(是的,我知道这是一个愚蠢的程序,使用std::vector等会更明智。)但我有一个更复杂的最终目标,学习如何使用各种模板将帮助我达到这个目标。)
本程序的执行情况:
Vobject@A000()
Vobject@A001()
Vobject@A002()
Vobject@A003()
Vobject@A004()
Vobject@A005()
completely default construction
Vobject@A006(1)
Vobject@A007()
Vobject@A008()
Vobject@A009()
Vobject@A010()
Vobject@A011()
fix_array Base was initialized
Vobject@A012(3, "foobar")
Vobject@A013()
Vobject@A014()
Vobject@A015()
Vobject@A016()
Vobject@A017()
fix_array Base was initialized
Vobject@A018(100,200,300)
Vobject@A019()
Vobject@A020()
Vobject@A021()
Vobject@A022()
Vobject@A023()
fix_array Base was initialized
Hello, world
~Vobject@A023 (was constructed Vobject(void))
~Vobject@A022 (was constructed Vobject(void))
~Vobject@A021 (was constructed Vobject(void))
~Vobject@A020 (was constructed Vobject(void))
~Vobject@A019 (was constructed Vobject(void))
~Vobject@A018 (was constructed Vobject(int,int,int))
~Vobject@A017 (was constructed Vobject(void))
~Vobject@A016 (was constructed Vobject(void))
~Vobject@A015 (was constructed Vobject(void))
~Vobject@A014 (was constructed Vobject(void))
~Vobject@A013 (was constructed Vobject(void))
~Vobject@A012 (was constructed Vobject(int,const char*))
~Vobject@A011 (was constructed Vobject(void))
~Vobject@A010 (was constructed Vobject(void))
~Vobject@A009 (was constructed Vobject(void))
~Vobject@A008 (was constructed Vobject(void))
~Vobject@A007 (was constructed Vobject(void))
~Vobject@A006 (was constructed Vobject(int))
~Vobject@A005 (was constructed Vobject(void))
~Vobject@A004 (was constructed Vobject(void))
~Vobject@A003 (was constructed Vobject(void))
~Vobject@A002 (was constructed Vobject(void))
~Vobject@A001 (was constructed Vobject(void))
~Vobject@A000 (was constructed Vobject(void))发布于 2022-03-13 23:21:18
我怀疑你在试图同时传递两个包裹时被卡住了。你可能会被困在那里,因为这是很直观的事情。不幸的是,直觉在这里失败了,因为从赤裸裸的函数参数中推断出的行为方式是直觉所不期望的。跟踪包的行为不同,很难知道第二个包什么时候开始和第一个包结束,而且错误并不总是很清楚。
在这种情况下,我喜欢做标准库所做的事情。std::pair是一种聚合两个元素的类型。它允许通过将参数元组传递给每个元素(构造函数8)来单独(就位)初始化每个元素。这与std::forward_as_tuple协同工作,这是一个标准的函数模板-- does转发。您可以向基和数组提供参数,以执行类似的操作。
剩下的问题只是如何提取元组元素。B在C++17的std::make_from_tuple中很容易实现。myArray没有相同的好处,因为c-样式数组是不规则的类型。不过,我们可以使用委托构造函数和实用程序std::index_sequence来构造数组。我也将在B中使用这种方法,因此总共只需要C++14。
template <class B, class T>
class fix_array : public B
{
public:
template <class... BRefs, class... DRefs>
fix_array(std::tuple<BRefs...> bArgs, std::tuple<DRefs...> dArgs)
: fix_array(std::move(bArgs), std::make_index_sequence<sizeof...(BRefs)>{}, std::move(dArgs), std::make_index_sequence<sizeof...(DRefs)>{})
{}
private:
T pData[5];
template <class... BRefs, std::size_t... Bidx, class... DRefs, std::size_t... Didx>
fix_array(std::tuple<BRefs...> bArgs, std::index_sequence<Bidx...>, std::tuple<DRefs...> dArgs, std::index_sequence<Didx...>)
: B( std::get<Bidx>(bArgs)... )
, pData{ std::get<Didx>(dArgs)... }
{
std::cerr << "fix_array Base was initialized" << std:: endl;
}
};这两个index_sequence参数是标记类型占位符,按顺序包含每个元组元素的索引。它们只是在正确的序号上展开和访问每个元组元素。std::get已经通过正确的引用类型在std::forward_as_tuple完成其操作之后提取元素。
https://stackoverflow.com/questions/71461265
复制相似问题