#include <iostream>
#include <type_traits>
namespace detail
{
template <typename T>
decltype(T::num_components, void(), std::true_type{}) has_num_components_impl(int);
template <typename T>
std::false_type has_num_components_impl(...);
}
template <typename T>
using has_num_components = decltype(detail::has_num_components_impl<T>(0));
template <typename T>
std::enable_if_t<!has_num_components<T>::value, std::size_t>
get_num_components() { return 1; }
template <typename T>
std::enable_if_t<has_num_components<T>::value, std::size_t>
get_num_components() { return T::num_components; }
template<class T>
void EmitAttribute(T const & v, int stride, int offset, int i)
{
std::cout << "Stride is "
<< stride
<< " element index "
<< i
<< " is at offset "
<< offset
<< " has "
<< get_num_components<T>()
<< " component "
<< std::endl;
}
template<class T, int C>
struct vec
{
typedef T value_type;
enum { num_components = C };
};
int main() {
vec<int, 42> v;
EmitAttribute(v, 1, 2, 3);
EmitAttribute(42, 1, 2, 3);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgpuYW1lc3BhY2UgZGV0YWlsCnsKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogICAgZGVjbHR5cGUoVDo6bnVtX2NvbXBvbmVudHMsIHZvaWQoKSwgc3RkOjp0cnVlX3R5cGV7fSkgaGFzX251bV9jb21wb25lbnRzX2ltcGwoaW50KTsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICAgIHN0ZDo6ZmFsc2VfdHlwZSBoYXNfbnVtX2NvbXBvbmVudHNfaW1wbCguLi4pOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KdXNpbmcgaGFzX251bV9jb21wb25lbnRzID0gZGVjbHR5cGUoZGV0YWlsOjpoYXNfbnVtX2NvbXBvbmVudHNfaW1wbDxUPigwKSk7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RkOjplbmFibGVfaWZfdDwhaGFzX251bV9jb21wb25lbnRzPFQ+Ojp2YWx1ZSwgc3RkOjpzaXplX3Q+CmdldF9udW1fY29tcG9uZW50cygpIHsgcmV0dXJuIDE7IH0KCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpzdGQ6OmVuYWJsZV9pZl90PGhhc19udW1fY29tcG9uZW50czxUPjo6dmFsdWUsIHN0ZDo6c2l6ZV90PgpnZXRfbnVtX2NvbXBvbmVudHMoKSB7IHJldHVybiBUOjpudW1fY29tcG9uZW50czsgfQoKCnRlbXBsYXRlPGNsYXNzIFQ+CnZvaWQgRW1pdEF0dHJpYnV0ZShUIGNvbnN0ICYgdiwgaW50IHN0cmlkZSwgaW50IG9mZnNldCwgaW50IGkpCnsKICAgIHN0ZDo6Y291dCA8PCAiU3RyaWRlIGlzICIKICAgICAgICAgICAgICA8PCBzdHJpZGUKICAgICAgICAgICAgICA8PCAiIGVsZW1lbnQgaW5kZXggIgogICAgICAgICAgICAgIDw8IGkKICAgICAgICAgICAgICA8PCAiIGlzIGF0IG9mZnNldCAiCiAgICAgICAgICAgICAgPDwgb2Zmc2V0CiAgICAgICAgICAgICAgPDwgIiBoYXMgIgogICAgICAgICAgICAgIDw8IGdldF9udW1fY29tcG9uZW50czxUPigpCiAgICAgICAgICAgICAgPDwgIiBjb21wb25lbnQgIgogICAgICAgICAgICAgIDw8IHN0ZDo6ZW5kbDsKfQoKdGVtcGxhdGU8Y2xhc3MgVCwgaW50IEM+CnN0cnVjdCB2ZWMKewogICAgdHlwZWRlZiBUIHZhbHVlX3R5cGU7CgogICAgZW51bSB7IG51bV9jb21wb25lbnRzID0gQyB9Owp9OwoKaW50IG1haW4oKSB7Cgl2ZWM8aW50LCA0Mj4gdjsKCQoJRW1pdEF0dHJpYnV0ZSh2LCAxLCAyLCAzKTsKCUVtaXRBdHRyaWJ1dGUoNDIsIDEsIDIsIDMpOwp9