title: Robust type caster for STL-vector-like classes
body: <p>I have a class that is quite similar to an STL-vector (the differences are not important for the pybind11 type caster, so I will ignore them here). I have written a type caster for this class. A minimal working example of my code is given below. An example showing the problem is included below the code.</p>
  
  <p>The problem is that my caster is quite limited (because I have used <code>py::array_t</code>). In principle the interface does accept tuples, lists, and numpy-arrays. However, when I overload based on typename, the interface fails for inputted tuples and lists (simply the first overload is selected even though it is the incorrect type).</p>
  
  <p>My question is: <em>How can I make the type caster more robust? Is there an effective way to re-use as much as possible existing type casters for STL-vector-like classes?</em></p>
  
  <h3>C++ code (including pybind11 interface)</h3>
  
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;pybind11/pybind11.h&gt;
  #include &lt;pybind11/stl.h&gt;
  #include &lt;pybind11/numpy.h&gt;
  
  namespace py = pybind11;
  
  // class definition
  // ----------------
  
  template&lt;typename T&gt;
  class Vector
  {
  private:
  
    std::vector&lt;T&gt; mData;
  
  public:
  
    Vector(){};
    Vector(size_t N) { mData.resize(N); };
  
    auto   data ()       { return mData.data (); };
    auto   data () const { return mData.data (); };
    auto   begin()       { return mData.begin(); };
    auto   begin() const { return mData.begin(); };
    auto   end  ()       { return mData.end  (); };
    auto   end  () const { return mData.end  (); };
    size_t size () const { return mData.size (); };
  
    std::vector&lt;size_t&gt; shape()   const { return std::vector&lt;size_t&gt;(1, mData.size()); }
    std::vector&lt;size_t&gt; strides() const { return std::vector&lt;size_t&gt;(1, sizeof(T)   ); }
  
    template&lt;typename It&gt; static Vector&lt;T&gt; Copy(It first, It last) {
      Vector out(last-first);
      std::copy(first, last, out.begin());
      return out;
    }
  };
  
  // C++ functions: overload based on type
  // -------------------------------------
  
  Vector&lt;int&gt;    foo(const Vector&lt;int&gt;    &amp;A){ std::cout &lt;&lt; "int"    &lt;&lt; std::endl; return A; }
  Vector&lt;double&gt; foo(const Vector&lt;double&gt; &amp;A){ std::cout &lt;&lt; "double" &lt;&lt; std::endl; return A; }
  
  // pybind11 type caster
  // --------------------
  
  namespace pybind11 {
  namespace detail {
  
  template&lt;typename T&gt; struct type_caster&lt;Vector&lt;T&gt;&gt;
  {
  public:
  
    PYBIND11_TYPE_CASTER(Vector&lt;T&gt;, _("Vector&lt;T&gt;"));
  
    bool load(py::handle src, bool convert)
    {
      if ( !convert &amp;&amp; !py::array_t&lt;T&gt;::check_(src) ) return false;
  
      auto buf = py::array_t&lt;T, py::array::c_style | py::array::forcecast&gt;::ensure(src);
      if ( !buf ) return false;
  
      auto rank = buf.ndim();
      if ( rank != 1 ) return false;
  
      value = Vector&lt;T&gt;::Copy(buf.data(), buf.data()+buf.size());
  
      return true;
    }
  
    static py::handle cast(const Vector&lt;T&gt;&amp; src, py::return_value_policy policy, py::handle parent)
    {
      py::array a(std::move(src.shape()), std::move(src.strides()), src.data());
  
      return a.release();
    }
  };
  
  }} // namespace pybind11::detail
  
  // Python interface
  // ----------------
  
  PYBIND11_MODULE(example,m)
  {
    m.doc() = "pybind11 example plugin";
  
    m.def("foo", py::overload_cast&lt;const Vector&lt;int   &gt; &amp;&gt;(&amp;foo));
    m.def("foo", py::overload_cast&lt;const Vector&lt;double&gt; &amp;&gt;(&amp;foo));
  }
  </code></pre>
  
  <h3>Example</h3>
  
  <pre class="lang-python prettyprint-override"><code>import numpy as np
  import example
  
  print(example.foo((1,2,3)))
  print(example.foo((1.5,2.5,3.5)))
  
  print(example.foo(np.array([1,2,3])))
  print(example.foo(np.array([1.5,2.5,3.5])))
  </code></pre>
  
  <p>Output:</p>
  
  <pre class="lang-none prettyprint-override"><code>int
  [1 2 3]
  int
  [1 2 3]
  int
  [1 2 3]
  double
  [1.5 2.5 3.5]
  </code></pre>