Lazily compute include set
diff --git a/gen/include.rs b/gen/include.rs
index ef741af..e34d9d0 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -1,3 +1,5 @@
+use std::fmt::{self, Display};
+
 pub static HEADER: &str = include_str!("include/cxxbridge.h");
 
 pub fn get(guard: &str) -> &'static str {
@@ -11,3 +13,43 @@
         panic!("not found in cxxbridge.h header: {}", guard)
     }
 }
+
+#[derive(Default)]
+pub struct Includes {
+    custom: Vec<String>,
+    pub cstdint: bool,
+    pub memory: bool,
+    pub string: bool,
+    pub type_traits: bool,
+}
+
+impl Includes {
+    pub fn new() -> Self {
+        Includes::default()
+    }
+
+    pub fn insert(&mut self, include: String) {
+        self.custom.push(include);
+    }
+}
+
+impl Display for Includes {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for include in &self.custom {
+            writeln!(f, "#include \"{}\"", include.escape_default())?;
+        }
+        if self.cstdint {
+            writeln!(f, "#include <cstdint>")?;
+        }
+        if self.memory {
+            writeln!(f, "#include <memory>")?;
+        }
+        if self.string {
+            writeln!(f, "#include <string>")?;
+        }
+        if self.type_traits {
+            writeln!(f, "#include <type_traits>")?;
+        }
+        Ok(())
+    }
+}
diff --git a/gen/out.rs b/gen/out.rs
index 506ce6c..124816f 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -1,8 +1,10 @@
+use crate::gen::include::Includes;
 use std::fmt::{self, Arguments, Write};
 
 pub(crate) struct OutFile {
     pub namespace: Vec<String>,
     pub header: bool,
+    pub include: Includes,
     content: Vec<u8>,
     section_pending: bool,
     blocks_pending: Vec<&'static str>,
@@ -13,6 +15,7 @@
         OutFile {
             namespace,
             header,
+            include: Includes::new(),
             content: Vec::new(),
             section_pending: false,
             blocks_pending: Vec::new(),
@@ -37,6 +40,10 @@
         }
     }
 
+    pub fn prepend(&mut self, section: String) {
+        self.content.splice(..0, section.into_bytes());
+    }
+
     pub fn write_fmt(&mut self, args: Arguments) {
         Write::write_fmt(self, args).unwrap();
     }
diff --git a/gen/write.rs b/gen/write.rs
index 68f0315..24c9c09 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -14,7 +14,7 @@
 
     for api in apis {
         if let Api::Include(include) = api {
-            writeln!(out, "#include \"{}\"", include.value().escape_default());
+            out.include.insert(include.value());
         }
     }
 
@@ -74,41 +74,25 @@
         write_generic_instantiations(out, types);
     }
 
+    out.prepend(out.include.to_string());
+
     out_file
 }
 
 fn write_includes(out: &mut OutFile, types: &Types) {
-    let mut has_int = false;
-    let mut has_box = false;
-    let mut has_unique_ptr = false;
-    let mut has_string = false;
-
     for ty in types {
         match ty {
             Type::Ident(ident) => match Atom::from(ident) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-                | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => has_int = true,
-                Some(CxxString) => has_string = true,
+                | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => out.include.cstdint = true,
+                Some(CxxString) => out.include.string = true,
                 Some(Bool) | Some(RustString) | None => {}
             },
-            Type::RustBox(_) => has_box = true,
-            Type::UniquePtr(_) => has_unique_ptr = true,
+            Type::RustBox(_) => out.include.type_traits = true,
+            Type::UniquePtr(_) => out.include.memory = true,
             _ => {}
         }
     }
-
-    if has_int {
-        writeln!(out, "#include <cstdint>");
-    }
-    if has_unique_ptr {
-        writeln!(out, "#include <memory>");
-    }
-    if has_string {
-        writeln!(out, "#include <string>");
-    }
-    if has_box {
-        writeln!(out, "#include <type_traits>");
-    }
 }
 
 fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {