index 可变模板展开
https://www.zhihu.com/question/51253466
#include <iostream>
#include <fstream>
#include <memory>
#include <iterator>
#include <type_traits>
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
#include <type_traits>
#include <typeinfo>
#ifndef _MSC_VER
# include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>
template <class T>
std::string type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void(*)(void*)> own
(
#ifndef _MSC_VER
abi::__cxa_demangle(typeid(TR).name(), nullptr,
nullptr, nullptr),
#else
nullptr,
#endif
std::free
);
std::string r = own != nullptr ? own.get() : typeid(TR).name();
if (std::is_const<TR>::value)
r += " const";
if (std::is_volatile<TR>::value)
r += " volatile";
if (std::is_lvalue_reference<T>::value)
r += "&";
else if (std::is_rvalue_reference<T>::value)
r += "&&";
return r;
}
using namespace std;
std::string demangle(const char* name);
inline std::string demangle(const char* name)
{
int status = -4;
std::unique_ptr<char, void(*)(void*)> res
{
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
template<int...>
struct IndexSeq {};
template<int N, int... Indexes>
struct MakeIndexes : MakeIndexes<N - 1, N - 1, Indexes...>
{
MakeIndexes()
{
Init(demangle(typeid(this).name()));
}
void Init(std::string id)
{
std::cout<<"Creating "<<id<<std::endl;
}
};
template<int... indexes>
struct MakeIndexes<0, indexes...>
{
typedef IndexSeq<indexes...> type;
MakeIndexes()
{
Init(demangle(typeid(this).name()));
}
void Init(std::string id)
{
std::cout<<"Creating "<<id<<std::endl;
}
};
int main()
{
MakeIndexes<3> a;
MakeIndexes<3>::type b;
std::cout<<"*************************************"<<std::endl;
std::cout<<type_name<decltype(a)>()<<std::endl;
std::cout<<type_name<decltype(b)>()<<std::endl;
}
[root@VM_99_227_centos dev]# ./a.out
Creating MakeIndexes<0, 0, 1, 2>*
Creating MakeIndexes<1, 1, 2>*
Creating MakeIndexes<2, 2>*
Creating MakeIndexes<3>*
*************************************
MakeIndexes<3>
IndexSeq<0, 1, 2>
继承关系:
MakeIndexes<3> : MakeIndexes<2, 2>
MakeIndexes<2, 2> : MakeIndexes<1,1,2>
MakeIndexes<1,1,2>: MakeIndexes<0, 0,1,2>
/********************/
template <typename... Ts, typename U> class X {}; // (1) error!
template <typename... Ts> class Y {}; // (2)
template <typename... Ts, typename U> class Y<U, Ts...> {}; // (3)
template <typename... Ts, typename U> class Y<Ts..., U> {}; // (4) error!
为什么第(1)条语句会出错呢?(1)是模板原型,模板实例化时,要以它为基础和实例化时的类型实参相匹配.因为C++的模板是自左向右匹配的,所以不定长参数只能结尾.其他形式,无论写作Ts, U,或者是Ts, V, Us,,或者是V, Ts, Us都是不可取的.(4) 也存在同样的问题.
但是,为什么(3)中, 模板参数和(1)相同,都是typename... Ts, typename U,但是编译器却并没有报错呢?
答案:(3)和(1)不同,它并不是模板的原型,它只是Y的一个偏特化.偏特化时,模板参数列表并不代表匹配顺序,它们只是为偏特化的模式提供的声明,也就是说,它们的匹配顺序,只是按照<U, Ts...>来,而之前的参数只是告诉你Ts是一个类型列表,而U是一个类型,排名不分先后.