Like others I was struggling to find usefulness of this and what problems it solves. I admit, it seems like a stretch. There was a situation in which I needed a template class to be implemented such that I wanted only certain types to be accepted one way and others a different way.<p>I implemented a stream buffer that can accept different types into the stream. Based on the type, the buffer would serialize and expand to accept the data.<p>To put this more succintly, an insert of unit8_t type would put a single byte into the stream buffer and an insert of uint16_t would put two bytes into the stream buffer. And I needed a way to make sure the types were plain old data types (int, char, uint8_t, uint16_t, uint_32_t, etc...)<p>Here is sample code:<p>template<typename T>
class TStream
{
private:<p><pre><code> typedef TBuffer<T> stream_buffer;
stream_buffer mStream;
</code></pre>
public:<p><pre><code> TStream();
TStream(const TStream &rhs);
TStream::~TStream();
unsigned int Size() const;
unsigned int ByteStreamLength() const;
void Clear();
// some methods omitted for brevity
const T&operator[](unsigned int idx);
const T*operator[](unsigned int idx) const;
TStream<T> &operator=(const TStream &rhs);
TStream<T> &operator=(T const);
TStream<T> &operator=(unsigned char);
TStream<T> &operator=(bool);
TStream<T> &operator=(double);
// rest omitted for brevity</code></pre>
};<p>Doing this<p>TStream<unsigned char> ByteStream<p>causes ambiguity with<p>operator=(unsigned char).<p>I basically want operator=(unsigned char) to be omitted if T = unsigned char.<p>The way I solved this, without Concepts of course, was to use CRTP like so:<p>template<typename D, typename T, typename U><p>struct implement_operator_plus_equals
{
implement_operator_plus_equals()
{
static_assert(std::is_base_of<implement_operator_plus_equals, D>::value, "CRTP failure" );
}
D* self() { return static_cast<D<i>>(this); }
D const</i> self() const { return static_cast<D const<i>>(this); }<p><pre><code> typedef D Self;
Self& operator+=( U u ) {
static_assert( (sizeof(U)%sizeof(T)) == 0, "Non integer number of Ts in a U" );
T* b = reinterpret_cast<T*>(&u);
T* e = b + sizeof(U)/sizeof(T);
for (T* it = b; it != e; ++it) {
self()->consume(*it);
return *self();
}</code></pre>
};
template<typename D, typename T>
struct implement_operator_plus_equals<D,T,T> {
implement_operator_plus_equals() {
static_assert(
std::is_base_of<implement_operator_plus_equals, D>::value, "CRTP failure"
);
// Have an operator+= that cannot be called, so using ...::operator+= is legal,
// but mostly harmless:
class block_call {};
void operator+=( block_call ) {}
}
};<p>I believe I could have solved this without CRTP using Concepts. Although my understanding is that Concepts follows a methodology of deny all, allow what is defined and there appears to be no way to allow all, deny what is specified as a Concept. In other words, Concepts only tell the compiler what is allowed and there appears to be no way to specify what is NOT allowed without some further "trickery."