我想制作一個模板,其引數 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;
}
(Yes, I understand that this is a silly program and it would be smarter to use std::vector and so on. But I have a more-complicated end goal, and learning how to use variadic templates would help me reach it.)
Execution of this program:
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))
uj5u.com熱心網友回復:
我懷疑你在嘗試同時通過兩個包時被卡住了。你可能會被困在那里,因為這是直覺的事情。不幸的是,直覺在這里失敗了,因為從裸函式引數中進行的包推導以直覺不期望的方式表現。尾隨包的行為不同,很難知道第二包何時開始和第一個結束,并且在此程序中遇到的錯誤并不總是很清楚。
在這種情況下,我喜歡簡單地做標準庫所做的事情。std::pair是一種聚合兩個元素的型別。它允許通過將一組引數傳遞給每個元素(建構式 8 )來單獨(就地)初始化每個元素。std::forward_as_tuple這與做轉發的標準功能模板協同作用。您可以為基數和陣列提供引數以執行類似的操作。
剩下的問題只是如何提取元組元素。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://www.uj5u.com/gongcheng/443091.html
