简体   繁体   中英

template C++ array

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.

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.

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]; };

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM