summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2017-02-09 13:50:32 -0800
committerNick Fitzgerald <fitzgen@gmail.com>2017-02-21 08:39:16 -0800
commit83c1a9594f5827451b7536352d53889b75230a57 (patch)
treed2ec6bd27abb2763bbab719003422b0644f527d4
parent40fc430d60fbdc62d6c24a2532526c45b9fba9f7 (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.rs67
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.