4
votes

I'm trying to accomplish

namespace NTL
{
    typedef std::valarray vector;
}

through standard C++. I know it's not allowed, but I need a quick and easy way (without reimplementing all functions, operators, overloads, etc.) to get a template typedef.

I am now doing a template class Vector which has a valarray as data member, but that will require me to overload all math functions for my vector (again... as valarray does it as well).

Any ideas? Thanks!

PS: I will probably need to extend the functionality of NTL::vector at some point, and a way to incorporate that in the solution would be awesome.

2

2 Answers

8
votes

In C++0x that will be really simple, but for the time being you can approach the problem in two ways, through a metafunction or by abusing inheritance.

namespace NTL {
   // metafunction
   template <typename T>
   struct vector_1 {
      typedef std::valarray<T> type;
   };

   // inheritance abuse:
   template <typename T>
   struct vector_2 : std::valarray<T>
   {};
}
int main() {
   NTL::vector_1<double>::type var1; // type is std::valarray<double>
   NTL::vector_2<double> var2;       // type inherits from std::valarray<double>
}

The second approach can be extended easily, but note that in general it is not recommended to inherit publicly from STL containers, as they were not designed to be extended. In particular since they don't have virtual destructor you can end up with undefined behavior if your object is deleted from a pointer to the STL container...

I would advise you to inherit privately and bring the base member functions into scope by means of a using declaration (better than providing public inheritance). It will require more boiler-plate code, but you won't need to provide forwarding methods for all your desired interface.

BTW, the C++0x way would be:

namespace NTL {
   template <typename T>
   using vector = std::valarray<T>;
}
1
votes

You could derive your NTL::vector class from std::valarray:

namespace NTL {
  template <class T>
  class vector : public std::valarray<T>
  {
  public:
    vector() : std::valarray<T>() { }
    vector(const std::valarray<T>& other) : std::valarray(other) { }
    /* other constructors to match the std::valarray constructors */

    vector& operator=(const vector& );
    vector& operator=(const std::valarray<T>& );
  };
}

This way, an NTL::vector gets converted to a std::valarray at the start of a sequence of operations, but the resulting valarray can also be converted to an NTL::vector again.

One big warning: As stl::valarray is not designed for polymorphic use, you will get into trouble if try to delete an NTL::vector object through a std::valarray pointer!