diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-02-09 13:50:32 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-02-21 08:39:16 -0800 |
commit | 83c1a9594f5827451b7536352d53889b75230a57 (patch) | |
tree | d2ec6bd27abb2763bbab719003422b0644f527d4 | |
parent | 40fc430d60fbdc62d6c24a2532526c45b9fba9f7 (diff) |
Add TemplateDeclaration::all_template_parameters
The all_template_parameters method gets the complete set of template parameters
that can affect a given item.
Note that this item doesn't need to be a template declaration itself for `Some`
to be returned from this method (in contrast to `self_template_params`). If this
item is a member of a template declaration, then the parent's template
parameters are included here. See the example in TemplateDeclaration's doc
comment for details.
-rw-r--r-- | src/ir/ty.rs | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 66136828..1b5ecc3c 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -7,7 +7,7 @@ use super::dot::DotAttributes; use super::enum_ty::Enum; use super::function::FunctionSig; use super::int::IntKind; -use super::item::Item; +use super::item::{Item, ItemAncestors}; use super::layout::Layout; use super::objc::ObjCInterface; use super::traversal::{Trace, Tracer}; @@ -16,7 +16,40 @@ use parse::{ClangItemParser, ParseError, ParseResult}; use std::io; use std::mem; -/// Template declaration related methods. +/// Template declaration (and such declaration's template parameters) related +/// methods. +/// +/// Consider this example: +/// +/// ```c++ +/// template <typename T, typename U> +/// class Foo { +/// template <typename V> +/// using Bar = V*; +/// +/// class Inner { +/// T x; +/// U y; +/// Bar<int> z; +/// }; +/// }; +/// +/// class Qux { +/// int y; +/// }; +/// ``` +/// +/// The following table depicts the results of each trait method when invoked on +/// `Foo`, `Bar`, and `Qux`. +/// +/// +------+----------------------+--------------------------+------------------------+ +/// |Decl. | self_template_params | num_self_template_params | all_template_parameters| +/// +------+----------------------+--------------------------+------------------------+ +/// |Foo | Some([T, U]) | Some(2) | Some([T, U]) | +/// |Bar | Some([V]) | Some(1) | Some([T, U, V]) | +/// |Inner | None | None | Some([T, U]) | +/// |Qux | None | None | None | +/// +------+----------------------+--------------------------+------------------------+ pub trait TemplateDeclaration { /// Get the set of `ItemId`s that make up this template declaration's free /// template parameters. @@ -38,6 +71,36 @@ pub trait TemplateDeclaration { fn num_self_template_params(&self, ctx: &BindgenContext) -> Option<usize> { self.self_template_params(ctx).map(|params| params.len()) } + + /// Get the complete set of template parameters that can affect this + /// declaration. + /// + /// Note that this item doesn't need to be a template declaration itself for + /// `Some` to be returned here (in contrast to `self_template_params`). If + /// this item is a member of a template declaration, then the parent's + /// template parameters are included here. + /// + /// In the example above, `Inner` depends on both of the `T` and `U` type + /// parameters, even though it is not itself a template declaration and + /// therefore has no type parameters itself. Perhaps it helps to think about + /// how we would fully reference such a member type in C++: + /// `Foo<int,char>::Inner`. `Foo` *must* be instantiated with template + /// arguments before we can gain access to the `Inner` member type. + fn all_template_params(&self, ctx: &BindgenContext) -> Option<Vec<ItemId>> + where Self: ItemAncestors + { + let each_self_params: Vec<Vec<_>> = self.ancestors(ctx) + .filter_map(|id| id.self_template_params(ctx)) + .collect(); + if each_self_params.is_empty() { + None + } else { + Some(each_self_params.into_iter() + .rev() + .flat_map(|params| params) + .collect()) + } + } } /// The base representation of a type in bindgen. |