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{};