38

Suppose I am a user of a Certain Template Library (CTL) which defines a template, named, say, Hector

template <class T>
class Hector {...};

And in its documentation it gives many guarantees about Hector template behavior. But then it also defines a specialization for a certain type Cool

template <>
class Hector<Cool> {....};

The purpose of the specialization is a more optimized implementation of Hector, but unfortunately because of this optimization many guarantees of Hector are violated.

Currently I really don't need the optimization, I'd rather preserve all the guarantees of Hector. Is there any way I could, without changing the library code (CTL is a highly respectable library, you know), circumvent the specialization? Any way at all? Maybe write some sort of wrapper? Anything? I just want to the compiler to generate code for Hector<Cool> in a normal, non-optimized way, with all the guarantees.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434

5 Answers5

12

You could wrap cool in a dummy type to prevent the template from specializing it.

Mikola
  • 9,176
  • 2
  • 34
  • 41
12

Are you able to use the related template Reque that doesn't have the undesired specialization? Otherwise I think you'd need to create a wrapper for Cool so that the specialization isn't used.

Mark B
  • 95,107
  • 10
  • 109
  • 188
8

No. And even if it can be done in some esoteric fashion, don't. Circumventing language features should set off an alarm.

You have to wrap the value or use a different type like char instead of bool (they behave similarly), giving std::vector<char> instead of std::vector<bool>.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 4
    who mentionned STDs and vectors ? – Alexandre C. Jun 27 '11 at 21:22
  • AFAIK the documentation gives no guaranteed that Cool and Shar have the same size, does it? – Armen Tsirunyan Jun 27 '11 at 21:24
  • 4
    @Armen : It's possible that `Cool` is larger than `Shar` but not smaller, and `Shar` is guaranteed to be able to hold all well-defined values of `Cool`. – ildjarn Jun 27 '11 at 21:25
  • 1
    @Armen: Correct, `Cool` can have any size, not necessarily one, but `Shar` definitely has a size of one. That said, you can do some magic (perhaps implementation-specific) to pick a non-`Cool` integral type that has the same size as `Cool`. – GManNickG Jun 27 '11 at 21:28
  • 3
    The more I think about this question, the more I think this is the right answer. After all, if what you want is for `vector` to behave "correctly", then you must be willing to take addresses of elements (after all, you did not tell what you expect precisely from Ctd::Hector). Therefore, using another integral type really makes sense (and will have the same semantics as bool, contrarily to the solution other people suggest with a wrapper). The good news is that you can even choose the size of the implementation. – Alexandre C. Jun 27 '11 at 21:32
7

Here's a little generic disguiser:

template <typename T>
struct Drool
{
  Drool(T d) : b(d) { }
  inline operator T() const { return b; }
  inline Drool<T> & operator=(T d) { b = d; return *this; }
private:
  T b;
};

Now you can say Hector<Drool<Cool>>.


Improved version according to Xeo:

template <typename T>
struct Drool
{
  Drool(const T & d) : b(d) { }
  Drool(Drool && o) = default;

  inline operator const T & () const { return b; }
  inline operator       T & ()       { return b; }

private:
  T b;
};
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 2
    Could be made even more generic by taking parameters as const-refs and adding a move-ctor for C++0x, but other than that, yeah. Also, no need for an `operator=`, as that is implicitly defined. – Xeo Jun 27 '11 at 21:36
  • @Kerrek: Also, should be `operator T&()` and `operator T const&() const`. :) – Xeo Jun 27 '11 at 22:16
  • @Xeo: I was actually wondering about that -- can the result of a cast be an lvalue? – Kerrek SB Jun 27 '11 at 22:18
  • @Xeo: Hm, OK, if I have `Drool x; T y;` and I say `x = y;`, this already invokes `x = Drool(y);`, so at what point would a cast come in useful as an lvalue? – Kerrek SB Jun 27 '11 at 22:23
1
  1. Open the standard certain implementation
  2. Ctrl+A
  3. Ctrl+C
  4. Create a new file called "my_hector.h"
  5. Ctrl+V
  6. Remove the specialisation
  7. Search and replace #include <hector> with #include "my_hector.h"
    [ Edit for @Xeo ;-) ]
  8. Rename identifiers that begin with two leading underscores followed by a lowercase letter, and all identifiers that begin with a single leading underscore following by an uppercase letter.
Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
  • 1
    I like this solution, actually :) Why not? – Armen Tsirunyan Jun 27 '11 at 21:29
  • @Armen: Because user-code is not allowed to use `_Identifier` or `__identifier`? ;) – Xeo Jun 27 '11 at 21:31
  • 4
    I don't like this solution because it gives up portability. – Alexandre C. Jun 27 '11 at 21:35
  • @Peter: It's not the standard implementation, it's a certain implementation :) – Armen Tsirunyan Jun 27 '11 at 21:37
  • 1
    @Armen: I never said standard... /nonchalant – Peter Alexander Jun 27 '11 at 21:38
  • Fail for not reading. You changed the library code. I mean, didn't change the originating "file" that was downloaded, but creating your own library is paramount to changing the originating code. – Lee Louviere Jun 27 '11 at 21:49
  • 2
    @Xaade: Umm, how is writing your own code equivalent to changing other code? – Peter Alexander Jun 27 '11 at 21:54
  • If this certain implementation uses search paths, you can place your "hector" file in a directory that is searched before . That would save you step 7. – Bo Persson Jun 27 '11 at 22:07
  • 1
    There is also an opportunity to break the ODR if you fail to replace `hector` by `my_hector.h` in *all* the indirectly included header files. So don't do this. Never. At least not on projects I'm working on. I wish I could downvote this more than once. – Alexandre C. Jun 27 '11 at 22:16
  • 1
    Instructions are incomplete - there's go guarantee that the template is implemented in a single file, and you might find yourself chasing down quite a lot of implementation-specific dependencies in order to isolate the certain implementation of Hector. – Steve Jessop Jun 27 '11 at 23:08
  • Another downvote for copypaste&tweak software development methodology. – ulidtko Nov 15 '12 at 19:50