views:

64

answers:

2

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.

+1  A: 

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>;
}
David Rodríguez - dribeas
Would there be a safe C++0x way of extending valarray without the additional mess, using this `using` statement? Thanks
rubenvb
@rubenvb: The funny C++ syntax is the equivalent of a templated typedef, it is not designed for extending the class but rather to fix some template arguments (consider that you want to have vectors of different element types with the same custom allocator, you can create a "typedefed" template that will fill the allocator for you).
David Rodríguez - dribeas
OK, thanks a lot.
rubenvb
+1  A: 

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!

Bart van Ingen Schenau
Two questions:1. This requires me to wrap all constructors of `std::valarray`, until my c++0x compiler has inherited constructor support? 2. Can I prevent an `NTL::vector` from being converted into a `std::valarray`, thus preventing any wrong `delete`s? Thanks
rubenvb
@rubenvb: 1. Yes, but most of the other members are not needed. You might also consider adding move-constructors if your compiler supports them. 2. You can, but that puts you in the same place as you are currently in with a `std::valarray` member.
Bart van Ingen Schenau
@Bart: Right, 2. was a stupid question, I knew that :). Thanks for the help.
rubenvb
If you want to disable conversion to `std::valarray` by using private inheritance, but then you will have to bring the `std::valarray` interface into your class by means of `using` declarations.
David Rodríguez - dribeas
@David: And you have to provide overloads for all the freestanding functions that currently accept a `std::valarray` and that you also want to use with the new class.
Bart van Ingen Schenau
David Rodríguez - dribeas