C++ 查找C+的结尾+;模板标识符列表
比方说,出于解析目的,其中一个想要跳过模板标识符列表的内容:C++ 查找C+的结尾+;模板标识符列表,c++,parsing,templates,C++,Parsing,Templates,比方说,出于解析目的,其中一个想要跳过模板标识符列表的内容: template<(valid code)> ^ ^ | from | to 模板 ^ ^ |从|到 首先想到的是盲目地找到第一个>,但这并不总是有效的: template<(valid code),template<(valid code)> > ^
template<(valid code)>
^ ^
| from | to
模板
^ ^
|从|到
首先想到的是盲目地找到第一个>,但这并不总是有效的:
template<(valid code),template<(valid code)> >
^ ^
| from | to, oops
模板
^ ^
|从|到,哎呀
更好的方法是递归跳过<和>对:
template<(valid code),template<(valid code)> >
^ ^
| from | to, better
模板
^ ^
|从|到,更好
然而,即使这种方法也不能用于像这样神秘但有效的杰作(来自bits\random.h,第69行,GCC 4.7.x):
模板
^ ^ ^ ^ ^ ^
|1 | 2 | 3 | 2 | 1 | 0去了哪里?
那么,我的问题是,找到任何有效模板标识符列表结尾的正确方法是什么?找到任何有效模板标识符列表结尾真的不容易,因为与
bits/random.h
中的示例相比,存在更多的病理可能性。(在这个答案的末尾有一个病理病例的例子:标识符是否为模板取决于大整数是否为素数。)
该算法易于说明(见C++11标准§14.2第3段,
[temp.names]
)。基本上,您需要跳过()
括号内的任何内容。
您需要查看
,并且Base::template type
是一个模板表达式
关键字typename
和template
,虽然在理解相关范围之前很难让你头脑清醒,但最终会让你的工作更轻松。否则,如果不编写完整的编译器,模板标识符列表的结束位置这一简单问题几乎不可能回答(即使这样,编译器也很难编写)
撇开依赖作用域不谈,您仍然需要能够处理非依赖作用域。这意味着您需要知道Base::type
是否为类型,这意味着要扫描每个struct/class/union
中的typedef
s,并使用语句解析基类typedef
s的公共继承和私有继承+
如果您将自己局限于编译的代码,那么您的工作仍然是可处理的,否则您将面临更多的工作
我不保证这就是一切,只是这很可能会让你忙上一段时间。暴力解析有很多潜在问题,比如宏、拆分行等。使用完整的AST解析器,即libclang。这个问题更多的是关于一般算法,而不是关于解析陷阱。不过谢谢你的建议。
template<(...),bool = __w < static_cast<size_t>(...)>
^ ^ ^ ^ ^ ^
| 1 | 2 | 3 | 2 | 1 | where did 0 go?
template <template <class> class T>
struct Base
{
template <class X>
using type = T<X>;
};
template <>
struct Base<std::numeric_limits>//Let's assume numeric_limits only has one template argument for this example
{
static const int type = 0;
};
template <class T, Base<T>::type < 0>
struct OtherClass{};