How to expose a templated class as one class to python with boost::python
<p>In many examples about boost::python you see something like:</p>

<pre><code>using namespace boost::python;
typedef class_&lt;std::vector&lt;float&gt;&gt; VectorFloat;
</code></pre>

<p>And then of course if you need a <code>double</code> vector you will have a second class called <code>DoubleVector</code> or so.
In my opinion this is not very "pythonic". It would be more intuitive (I think), if one (templated) class in C++ is actually one class in python which takes an argument like <code>, ..., type='float', ... ,</code>. This way the class also appears only once in the pydocs and has to be added only once to the <code>boost::python module</code>.</p>

<p>So let's say we have a simple templated class for our C++ code:</p>

<pre><code>template &lt;typename T&gt;
MyClass
{
    T val;

public:
    MyClass(const T&amp; tVal) : val(tVal) {}

    T    getVal()              { return val; }
    void setVal(const T&amp; tVal) { val = tVal; }
};
</code></pre>

<p>Now we want to write an interface for Python. My idea so far:</p>

<p><strong>Using boost::variant</strong></p>

<pre><code>typedef boost::variant&lt;MyClass&lt;float&gt;, MyClass&lt;double&gt;&gt; VariantClass;    

class MyPythonClass
{
    VariantClass vClass;

public:
    MyPythonClass(
        const PyObject&amp; tVal, 
        const boost::python::str&amp; type)
    {
        using namespace boost::python;
        std::string type_string = extract&lt;std::string&gt;(type);

        if( type_string == "float" )
        {
            float f = extract&lt;float&gt;(tVal);
            vClass = MyClass(f);
        }
        else if( type_string == "double" )
        {
            double d = extract&lt;double&gt;(tVal);
            vClass = MyClass(d);
        }
    }

    boost::python::PyObject* getVal()
    {
        // What to put here?
    }

    void setVal(const boost::python::PyObject&amp; tVal)
    {
        //What to put here?
    }
};

BOOST_PYTHON_MODULE(my_module)
{
    class_&lt;MyPythonClass&gt;("MyClass", init&lt;boost::python::PyObject, int, boost::python::str&gt;).def("getVal", &amp;MyClass::getVal());
}
</code></pre>

<p>A clear drawback of this solution is I guess that boost::variant can work with types that are quite different wheras my classes are almost identitcal, except for the type of data they store. So probably more information is abstracted away than necessary.</p>

<p>So the question I guess boils down to the two empty functions in the example. However, cleaner and shorter or less "if"-chain like answers will of course also be accepted. As the title says, it is about templated classes and boost::python and not necessarily about boost::variant.</p>

<p>There's a couple sources of confusion here. First, in Python, <code>object</code> is already basically a variant - everything is an <code>object</code>. And in C++, a class template isn't a type - it's a recipe for creating a type. So if you want to expose <code>MyClass&lt;T&gt;</code> from C++ to Python, you should just expose all the <code>MyClass&lt;T&gt;s</code></p>

<p>I would write a function template that does the bindings:</p>

<pre><code>template &lt;class T&gt;
void bind_MyClass(const char* name) {
    class_&lt;MyClass&lt;T&gt;&gt;(name, init&lt;T const&amp;&gt;())
        .add_property("val", &amp;MyClass&lt;T&gt;::getVal, &amp;MyClass&lt;T&gt;::setVal);
        ;
}
</code></pre>

<p>And then just call it:</p>

<pre><code>bind_MyClass&lt;float&gt;("MyClassFloat");
bind_MyClass&lt;double&gt;("MyClassDouble");
</code></pre>

python c++ templates boost boost-python