#include <iostream>
#include <type_traits>
// To define another operator
struct Dummy
{};
// Traits class
template <typename T, typename = void>
struct VectorTraits_impl
{
};
template <typename T>
struct VectorTraits_impl<T, std::enable_if_t<std::is_integral<decltype(T::dimension)>::value>>
{
typedef T VectorType;
typedef typename T::ValueType ValueType;
static const std::uint16_t dimension = T::dimension;
};
// Traits class
template <typename T>
using VectorTraits = VectorTraits_impl<T>;
// Fake vector class. Defines the required typedef.
struct Vec
{
typedef float ValueType;
static const std::uint16_t dimension = 2;
};
// Fake vector class. Defines the required typedef.
struct VecFake
{
};
template <>
struct VectorTraits_impl<VecFake>
{
typedef VecFake VectorType;
typedef float ValueType;
static const std::uint16_t dimension = 12;
};
// Streaming operator for Dummy.
std::ostream& operator<<(std::ostream& stream, const Dummy&)
{
stream << "dummy.\n";
return stream;
}
// Streaming operator attempt for classes defining VectorTraits.
template <class T, typename = std::enable_if_t<(VectorTraits<T>::dimension > 0)>>
std::ostream& operator << (std::ostream& stream, const T& )
{
return stream << "Traits. Dimension = " << VectorTraits<T>::dimension << "\n";
}
int main()
{
std::cout << "Test\n";
std::cout << Vec();
std::cout << VecFake();
std::cout << Dummy();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgovLyBUbyBkZWZpbmUgYW5vdGhlciBvcGVyYXRvcgpzdHJ1Y3QgRHVtbXkKe307CgovLyBUcmFpdHMgY2xhc3MKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lID0gdm9pZD4Kc3RydWN0IFZlY3RvclRyYWl0c19pbXBsCnsKfTsKCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IFZlY3RvclRyYWl0c19pbXBsPFQsIHN0ZDo6ZW5hYmxlX2lmX3Q8c3RkOjppc19pbnRlZ3JhbDxkZWNsdHlwZShUOjpkaW1lbnNpb24pPjo6dmFsdWU+Pgp7CiAgdHlwZWRlZiBUICAgICAgICAgICAgICAgICAgICAgICBWZWN0b3JUeXBlOwogIHR5cGVkZWYgdHlwZW5hbWUgVDo6VmFsdWVUeXBlICAgVmFsdWVUeXBlOwogIHN0YXRpYyBjb25zdCBzdGQ6OnVpbnQxNl90ICAgICAgZGltZW5zaW9uID0gVDo6ZGltZW5zaW9uOwp9OwoKLy8gVHJhaXRzIGNsYXNzCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgp1c2luZyBWZWN0b3JUcmFpdHMgPSBWZWN0b3JUcmFpdHNfaW1wbDxUPjsKCi8vIEZha2UgdmVjdG9yIGNsYXNzLiBEZWZpbmVzIHRoZSByZXF1aXJlZCB0eXBlZGVmLgpzdHJ1Y3QgVmVjCnsKICB0eXBlZGVmIGZsb2F0ICAgVmFsdWVUeXBlOwogIHN0YXRpYyBjb25zdCBzdGQ6OnVpbnQxNl90IGRpbWVuc2lvbiA9IDI7Cn07CgovLyBGYWtlIHZlY3RvciBjbGFzcy4gRGVmaW5lcyB0aGUgcmVxdWlyZWQgdHlwZWRlZi4Kc3RydWN0IFZlY0Zha2UKewp9OwoKdGVtcGxhdGUgPD4Kc3RydWN0IFZlY3RvclRyYWl0c19pbXBsPFZlY0Zha2U+CnsKICB0eXBlZGVmIFZlY0Zha2UgICAgICAgICAgICAgICAgICAgICAgIFZlY3RvclR5cGU7CiAgdHlwZWRlZiBmbG9hdCAgIFZhbHVlVHlwZTsKICBzdGF0aWMgY29uc3Qgc3RkOjp1aW50MTZfdCAgICAgIGRpbWVuc2lvbiA9IDEyOwp9OwoKLy8gU3RyZWFtaW5nIG9wZXJhdG9yIGZvciBEdW1teS4Kc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgc3RyZWFtLCBjb25zdCBEdW1teSYpCnsKICAgIHN0cmVhbSA8PCAiZHVtbXkuXG4iOwogICAgcmV0dXJuIHN0cmVhbTsKfQoKLy8gU3RyZWFtaW5nIG9wZXJhdG9yIGF0dGVtcHQgZm9yIGNsYXNzZXMgZGVmaW5pbmcgVmVjdG9yVHJhaXRzLgp0ZW1wbGF0ZSA8Y2xhc3MgVCwgdHlwZW5hbWUgPSBzdGQ6OmVuYWJsZV9pZl90PChWZWN0b3JUcmFpdHM8VD46OmRpbWVuc2lvbiA+IDApPj4Kc3RkOjpvc3RyZWFtJiBvcGVyYXRvciA8PCAoc3RkOjpvc3RyZWFtJiBzdHJlYW0sIGNvbnN0IFQmICkKewogICAgcmV0dXJuIHN0cmVhbSA8PCAiVHJhaXRzLiBEaW1lbnNpb24gPSAiIDw8IFZlY3RvclRyYWl0czxUPjo6ZGltZW5zaW9uIDw8ICJcbiI7Cn0KCmludCBtYWluKCkKewogICAgc3RkOjpjb3V0IDw8ICJUZXN0XG4iOwogICAgc3RkOjpjb3V0IDw8IFZlYygpOwogICAgc3RkOjpjb3V0IDw8IFZlY0Zha2UoKTsKICAgIHN0ZDo6Y291dCA8PCBEdW1teSgpOwp9