1

I wish to define a type String such that declaring a variable of type String is at compile-time equivalent to char[N]. I have seen examples of template functions of certain array dimension but none to work on actual concrete types themselves.

namespace myns {

   typedef uint32_t LongCount;
   typedef uint16_t ShortCount;

   typedef uint32_t LongDist;
   typedef uint16_t ShortDist;

   #define LONG_NAME 20;
   #define SHORT_NAME 10;

   // this would be better in my opinion:
   typedef String<20> LongName;
   typedef String<10> ShortName;


template<typename DIST1, typename DIST2, typename COUNT1>
struct SomeStruct1Base
{
   DIST1 dist1;
   DIST2 dist2;
   COUNT1 c;
};

typedef SomeStruct1Base<LongDist, LongDist, LongCount> SomeStruct1Long;
typedef SomeStruct1Base<ShortDist, ShortDist, ShortCount> SomeStruct1Short;

template<typename DIST1, typename COUNT1, int NAME_LEN>
struct SomeStruct2Base
{
   DIST1 dist1;
   uint32_t distx;
   COUNT1 c;
   char   name[NAME_LEN];
};

typedef SomeStruct2Base<LongDist, LongCount, SHORT_NAME> SomeStruct2Long;
typedef SomeStruct2Base<LongDist, LongCount, SHORT_NAME> SomeStruct2Short;
typedef SomeStruct2Base<LongDist, LongCount, LONG_NAME> SomeStruct2Ext;

The above is not very consistent and I think it would be better to pass in String<6> or whatever instead of passing in an int parameter to the template. No?

Update: I am using this structure to parse network data represented in char buffers so the struct needs to be able to do reinterpret_cast<>able. Sorry I didn't mention this earlier but I'm mentioning it now as I see some of the suggestions will break under the circumstance.

6
  • 1
    What did you try to achieve that goal? Commented Apr 25, 2011 at 21:19
  • 4
    Trust me, you don't want to do this. Commented Apr 25, 2011 at 21:20
  • I want to do this because I am parameterizing a whole bunch of structs with types and I wish to be able to pass the char[] size in the template parameters for my structs. Right now, I'm doing MyTemplate<uint32_t, char, 6, uint32_t>. It's also not possible to typedef my 6 to a more useful name either - I have to use #define which has it's own issues. Commented Apr 25, 2011 at 21:53
  • We just cannot see the advantage of having String<20> and String<21> as different types. Or why strcpy is useful here. Commented Apr 25, 2011 at 22:08
  • 1
    @chriskirk: Use C++11 std::array, also known as C++03 tr1::array and boost::array, for the data structure, and use enum to give names to template numeric arguments. Commented Apr 25, 2011 at 22:49

3 Answers 3

4

Use a std::size_t parameter in your template, then provide an overload of operator char*. Like this:

template <std::size_t N>
class String {
  public:
    operator char*()
    {
        return data;
    }
  private:
    char data[N];
};

Some people think that operator char* (and other implicit conversion operators) are bad, and they might be right. You should really read about the dangers of using it before you commit to using this, because it's not always the best idea.

Sign up to request clarification or add additional context in comments.

7 Comments

@Chris It's hard to see what this gives you over a naked char[N].
@unapersson - OP merely asked how to do it. Theretically you could add some safer methods to the class and discourage (or disable) the use of operator char*. It could be used as a transitional tool to port code that uses char* or char[] to a real string class.
@Chris fair enough. However, I'm far from convinced that any such "transitional" tool is required, desirable or possible.
@unapersson - It would help you keep your code compiling and working (which presumably it does, otherwise you wouldn't be concerned with preserving it's current state) while you isolate and update individual lines. It's arguably better than instantly breaking everything and having to fix it all at once.
Please see my comment in the OP
|
0

You can use following struct:

template<unsigned int SIZE>
struct String { typedef char t[SIZE]; };

Usage:

int main ()
{
  char a[20];
  String<20>::t b;
  //sizeof(a) = sizeof(b); both are equivalent
}

In fact you can make it generalize for any type:

template<typename T, unsigned int SIZE>
struct MyArray { typedef T t[SIZE]; };

Comments

-1

You can add the operator= to allow even cooler assignments:

template <size_t N>
class String {
  public:
    operator char*()
    {
        return data;
    }

    String& operator=(char* const &rhs)
    {
        strcpy_s(data, N, rhs);
        return *this;
    }
  private:
    char data[N];
};

int main()
{
    String<20> str;
    // You can do this:
    str = "This can be done";

    String<40> another;
    // And this:
    another = str;

    // ... and this:
    another = str = "Ciao";
}

Note that you should use strcpy_s.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.