Why can't namespaces be templated?

Viewed 629

I'm working on a library which has several template classes, all interrelated to such an extent that they all have the same template parameters. In a sense, a given template parameter set describes an nearly-self-contained universe of classes, maybe with a one or two routes between these class universes.

In current C++, I have no real way of grouping such 'class universes' together, except in a rather ugly and manual way. Here's an example of some inter-related templated classes that might highlight my point:

template<size_t dimension>
using vector_t = std::array<double, dimension>;

template<typename weight_t, size_t outer_dimension, size_t inner_dimension>
class A{
protected:
    weight_t weight;
public:
    weight_t get_weight(
        const vector_t<outer_dimension>& foo,
        const vector_t<inner_dimension>& bar
    ) const;
};

template<typename weight_t, size_t outer_dimension, size_t inner_dimension>
class B{
protected:
    std::vector<std::shared_ptr<A<weight_t, outer_dimension, inner_dimension>>> A_vector;
};

template<typename weight_t, size_t outer_dimension, size_t inner_dimension>
class C{
protected:
    std::vector<std::shared_ptr<A<weight_t, outer_dimension, inner_dimension>>> A_vector;
    std::vector<std::shared_ptr<B<weight_t, outer_dimension, inner_dimension>>> B_vector;
public:
    typename std::enable_if<
        (inner_dimension > 0),
        C<weight_t, outer_dimension + 1, inner_dimension - 1>
    >::type do_something() const;
};

This is usable - and, in the actual library I'm working on, the structure is ideal for what I want to use it for. It is, on the other hand, extremely ugly, and rather explicit for my liking.

If templated namespaces existed in the C++ standard, I could do something a little nicer:

template<size_t dimension>
using vector_t = std::array<double, dimension>;

template<typename weight_t, size_t outer_dimension, size_t inner_dimension>
namespace universe{
    typedef vector_t<outer_dimension> outer_vector;
    typedef vector_t<inner_dimension> inner_vector;

    class A{
    protected:
        weight_t weight;
    public:
        weight_t get_weight(const outer_vector& foo, const inner_vector& bar) const;
    };

    class B{
    protected:
        std::vector<std::shared_ptr<A>> A_vector;
    };

    class C{
    protected:
        std::vector<std::shared_ptr<A>> A_vector;
        std::vector<std::shared_ptr<B>> B_vector;
    public:
        typename std::enable_if<
            (inner_dimension > 0),
            universe<weight_t, outer_dimension + 1, inner_dimension - 1>::C
        >::type do_something() const;
    };
}

Of course, templated namespaces don't exist in the C++ standard. There are some really hacky approaches to get around this, e.g. "templating" a namespace. Solutions include:

  • using typedefs to make the whole point of templating redundant
  • wrapping typedefs in namespaces to make the point of redundant templating even more redundant.
  • having a 'types' struct, which is more preferable than the above two but still ugly (IMO).

Obviously, such solutions are workarounds to the fundamental issue - that namespaces can't be templated. Is there a specific reason that this has not been adopted by the standard, or is it simply something that is yet to be proposed (in an effective manner)?

I can see a variety of other use cases - for example, there are many generic libraries out there with a lot of focus on a single typedef template parameter, which could benefit from one overall parameter.

0 Answers
Related