abi*_*bir 16 c++ templates c++11
我正在使用一个带有一组整数的模板化类.代码就像,
template<unsigned... Idx>
struct work{ ... };
Run Code Online (Sandbox Code Playgroud)
然后我意识到,用户可能需要提供一组整数或一系列整数.所以,我改变了语法,以支持实例化,如,
work<indexes<1,3,2,4> > //instead of work<1,3,2,4>
work<span<1,4> > //same as work<1,2,3,4>
Run Code Online (Sandbox Code Playgroud)
同时,在C++,我们有大量的运营商,并且可以被用于配制异国表达式模板(比方说boost::xpressive,boost::lambda,boost::spirit等等),用于类型操纵可能性要少得多.
在Sean Parent的一个boostcon主题演讲中,他指出一个仍然不能写pair<int>的表示a pair of integers.在我的persinal库中,我做了一个语法,就像tuple<int[3]>表示一个3个整数的元组,而不是在类型参数中写一个带有3个int的元组,注意到我没有在任何地方写一个原始数组作为元组参数!(注意:std::array<int,3>与上面不一样,因为std :: array不能存储引用,tuple可以说std::tuple<int&,int&,int&>,可以)
所以,我想知道我能写的不同类型的"类型表达式"是什么?
到目前为止,我可以想到对象类型,函数类型,引用类型,有/无cv修饰符,指针等
template<class T>
struct tpl;
using t1 = tpl<int>;//simple type
//function (can have function pointer/reference also)
// e.g. void(*)(int,float) or void(&)(int,float)
using t2 = tpl<void(int,float)>;
//array can have pointer / reference also
//e.g. int(&)[4] or int (*)[4]
using t3 = tpl<int[4]>;
using t4 = tpl<int[]>;
using t5 = tpl<int const>;//with cv modifiers
using t6 = tpl<int*>;//with pointer
using t7 = tpl<int&>;//with reference (& or &&)
using t8 = tpl<tpl<int> >; //template itself
using t9 = tpl<void(...)>; //variadic functions
using t10 = tpl<R C::*>; //pointer to member
Run Code Online (Sandbox Code Playgroud)
但我相信,还有更多是可能的.
注意:这个问题纯粹是理论上的,我只是想知道我可以在<>中作为类型参数编写的各种语法,而不是关于它的可读性/道德方面,甚至我如何实现我拥有的一些例子给予,像工人阶级一样.
wil*_*llj 12
可以使用声明符语法构造复合类型 - 在中找到[dcl.decl].
这种语法的基础是六个基本结构,其中任何T都可以被列表中的任何其他结构替代.[在下文中,(T)表示零个或多个类型的列表(可以以'...'结尾),并<T>表示一个或多个类型的列表.
T // T
T* // pointer to T
T& // reference to T
T[n] // array of size 'n' of T
T C::* // pointer to C::member of type T
T (T) // function taking '(T)' and returning T
Run Code Online (Sandbox Code Playgroud)
编辑:类模板专业化的类型可以替代任何T:
C<T> // specialization of class template C with arguments '<T>'
Run Code Online (Sandbox Code Playgroud)
以上组合产生具有特殊意义的构造:
T (*)(T) // pointer to function taking '(T)' and returning T
T (C::*)(T) // pointer to C::member-function taking '(T)' and returning T
Run Code Online (Sandbox Code Playgroud)
另外,一些构造可能是cv限定的:
const T // const T
T* const // const pointer to T
T C::* const // const pointer to C::member of type T
Run Code Online (Sandbox Code Playgroud)
并非所有组合都会产生有效类型.根据[basic.compound],只能使用以下组合:
化合物类型可以通过以下方式构建:
- 给定类型的对象数组
- 函数,具有给定类型的参数并返回void或给定类型的引用或对象
- 指向void或指定类型的对象或函数(包括类的静态成员)的指针
- 对给定类型的对象或函数的引用
- 指向非静态类成员的指针,用于标识给定类的对象内给定类型的成员
提到了其他限制:
[dcl.ptr]没有指向引用的指针
[dcl.ref]不应引用引用,不引用引用数组,也不引用引用指针
[dcl.mptr]指向成员的指针不应指向......具有引用类型的成员,或"cv void".
[dcl.fct]参数列表(void)等效于空参数列表.除了这种特殊情况,void不应该是参数类型....如果参数的类型包括"指向T的未知界限的数组的指针"或"对T的未知界限的数组的引用"的形式,则该程序是错误的.函数不应具有类型数组或函数的返回类型.
某些可能的构造不能用作模板参数.当您显式指定一组模板参数时,编译器必须检查template-arguments是否可以替换模板参数,而不会导致"无效类型".根据[temp.deduct]\2,以下构造构成无效类型:
由于以下原因,类型扣除可能会失败:
尝试创建具有void,函数类型或引用类型的元素类型的数组,或尝试创建大小为零或负的数组.
Run Code Online (Sandbox Code Playgroud)template <class T> int f(T[5]); int I = f<int>(0); int j = f<void>(0); // invalid array试图在限定名称中使用不是类类型的类型.
Run Code Online (Sandbox Code Playgroud)template <class T> int f(typename T::B*); int i = f<int>(0);尝试在限定名称的限定符部分中使用类型,该类型在该类型不包含指定成员时命名类型,或者指定的成员不是需要类型的类型.
Run Code Online (Sandbox Code Playgroud)template <class T> int f(typename T::B*); struct A {}; struct C { int B; }; int i = f<A>(0); int j = f<C>(0);试图创建指向引用类型的指针.
尝试创建对引用类型的引用或对void的引用.
当T不是类类型时,尝试创建"指向T成员的指针".
Run Code Online (Sandbox Code Playgroud)template <class T> int f(int T::*); int i = f<int>(0);尝试在模板参数表达式或函数声明中使用的表达式中执行无效转换.
Run Code Online (Sandbox Code Playgroud)template <class T, T*> int f(int); int i2 = f<int,1>(0); // can’t conv 1 to int*试图创建一个函数类型,其中参数的类型为void.
- 试图创建一个cv限定的函数类型.
编辑:这是基于C++ 03,但也适用于C++ 11(添加右值引用类型)
我不完全确定你在问什么.我认为你给的样本很有趣,并且有点玩.
我想出了让一个实现span<a,b>是一个模板别名为indexes<a, ..., b>,使用类型推演的绝招constexpr功能:
template <int a, int b> using span = decltype(expand_span<a,b>());
Run Code Online (Sandbox Code Playgroud)
现在你可以吃蛋糕了:
////////////////////////////////////////////////////////////////
// using indirect template arguments
template<typename> struct indirect_work { };
void test_indirect()
{
indirect_work<indexes<1,2,3,4>> x;
indirect_work<span<1,4>> y;
x = y; // x and y are of identical types
static_assert(std::is_same<indexes<1,2,3,4>, span<1,4>>::value, "fact check");
}
Run Code Online (Sandbox Code Playgroud)
但是,也许更有趣的是,您仍然可以让主work模板采用原始<int...>模板参数列表:
////////////////////////////////////////////////////////////////
// using direct template arguments
template<int...> struct direct_work { };
// deduction alias:
template<int... direct> constexpr direct_work<direct...> deduction_helper(indexes<direct...>);
template <typename Idx> using deduce = decltype(deduction_helper(Idx{}));
void test_direct()
{
direct_work<1,2,3,4> x;
deduce<indexes<1,2,3,4>> y;
deduce<span<1,4>> z;
static_assert(std::is_same<decltype(x), decltype(y)>::value, "fact check");
static_assert(std::is_same<decltype(x), decltype(z)>::value, "fact check");
}
Run Code Online (Sandbox Code Playgroud)
在这里查看完整的工作演示:gcc on ideone.我在本地用clang编译它.
expand_span在这里重复的代码链接应该死了:
#include <type_traits>
template <int...> struct indexes {};
namespace {
template<int a, int... other>
constexpr indexes<a, other...> combine(indexes<other...> deduce);
template<int a, int b, typename Enable = void> struct expand_span_; // primary
template<int a, int b>
struct expand_span_<a, b, typename std::enable_if< (a==b), void >::type> {
static constexpr indexes<a> dispatch();
};
template<int a, int b>
struct expand_span_<a, b, typename std::enable_if< (a<b), void >::type> {
static constexpr decltype(combine<a>(expand_span_<a+1, b>::dispatch()))
dispatch();
};
template<int a, int b>
constexpr auto expand_span() -> decltype(expand_span_<a,b>::dispatch());
}
template <int a, int b> using span = decltype(expand_span<a,b>());
////////////////////////////////////////////////////////////////
// using indirect template arguments
template<typename> struct indirect_work { };
void test_indirect()
{
indirect_work<indexes<1,2,3,4>> x;
indirect_work<span<1,4>> y;
x = y; // x and y are of identical types
static_assert(std::is_same<indexes<1,2,3,4>, span<1,4>>::value, "fact check");
}
////////////////////////////////////////////////////////////////
// using direct template arguments
template<int...> struct direct_work { };
// deduction alias:
template<int... direct> constexpr direct_work<direct...> deduction_helper(indexes<direct...>);
template <typename Idx> using deduce = decltype(deduction_helper(Idx{}));
void test_direct()
{
direct_work<1,2,3,4> x;
deduce<indexes<1,2,3,4>> y;
deduce<span<1,4>> z;
static_assert(std::is_same<decltype(x), decltype(y)>::value, "fact check");
static_assert(std::is_same<decltype(x), decltype(z)>::value, "fact check");
}
int main()
{
test_indirect();
test_direct();
}
Run Code Online (Sandbox Code Playgroud)