1

OK, this is my first foray into templates, and this will likely be the first of several very silly, simple questions.

Consider:

template <class T>
void sendit(char *buffer, unsigned len)
{
   // force compile error
}

void sendit<first_valid>(char *buffer, unsigned len)
{
   // this is OK
}


void sendit<second_valid>(char *buffer, unsigned len)
{
   // this is OK
}

Basically, the idea is that I have a set of "things" that may legally be operated on by the sendit() procedure, and I will specialize the template for those things. If a user tries to call sendit(), (OK, technically, sendit()), I want to throw a compilation error in his face.

Is this do-able? If so, how?

Is this a reasonable approach?

John R. Strohm
  • 7,547
  • 2
  • 28
  • 33
  • Is this just autodidactic? Because unless you're just trying to learn what templates can do, I see no reason to use a template for this at all. – Beta Dec 12 '12 at 23:32
  • This is only part of what I'm trying to do. I have a set of around a dozen items, and four procedures. One can be applied to all of them, the other three are applicable to fixed subsets. There is other data that I plan to hide under the specializations. The end goal is to make the final setup as simple and idiot-proof as I reasonably can. – John R. Strohm Dec 12 '12 at 23:39
  • Possible duplicate of [How to prevent non-specialized template instantiation?](http://stackoverflow.com/questions/7064039/how-to-prevent-non-specialized-template-instantiation) – mako Jun 23 '16 at 01:36

1 Answers1

3

Leave it undefined:

template <class T>
void sendit(char *buffer, unsigned len);

// C++11
template <class T>
void sendit(char *buffer, unsigned len) = delete;

Using = delete is the preferred method IMO.

Or, do some type of static assertion (use Boost in C++03):

template <class T>
void sendit(char *buffer, unsigned len) {
    static_assert(sizeof(T) == 0, "must specialize"); // must use sizeof to make it dependant on T
}

Anyway, are you sure you really need type templates here? I'm not saying you shouldn't, just be aware there are alternatives involving overloads such as:

// This is only if you're using the types as tags
// Don't do this otherwise!!!

void sendit(first_valid, char *buffer, unsigned len)
{
   // this is OK
}


void sendit(second_valid, char *buffer, unsigned len)
{
   // this is OK
}

sendit(first_valid(), ...); // call first
sendit(second_valid(), ...); // call second

Or using enums instead of a type as the template parameter:

enum foo { first, second }

template <foo Foo>
void sendit(char *buffer, unsigned len);

void sendit<first>(char *buffer, unsigned len)
{
   // this is OK
}
Pubby
  • 51,882
  • 13
  • 139
  • 180
  • I had pretty much the same thing in mind (although strictly speaking this is a *linking* error, not a *compilation* error). – Beta Dec 12 '12 at 23:41
  • There are other things going on. The template parameters are going to be names of fields in a struct. The procedures will use the fieldname to grab the offset in the struct and the size of the field, and use that to control the write operation. (Including the length field was an error on my part: sue me.) What I'm trying to do is prevent the applications programmer who has to use this from making the usual silly error, like trying to write 47 bytes to something that can only take 23. (There's a hardware interprocessor connection involved.) – John R. Strohm Dec 12 '12 at 23:47
  • @JohnR.Strohm There may be a better way to do that, but I'm a little confused at what you want. Could you update your question showing example cases you want to prevent? – Pubby Dec 12 '12 at 23:50