#include <iostream>
#include <type_traits>
// Wrapper #######################################
template<class T>
struct Wrapper {typedef T WrappedType;};
template<class T, class Enable=void>
struct IsWrapper: std::false_type {};
template<class T>
struct IsWrapper<Wrapper<T> >: std::true_type {};
// WrapperTraits #######################################
template<
class T,
bool HasWrapper=
IsWrapper<T>::value && IsWrapper<typename T::WrappedType>::value>
struct GetRootType {
static_assert(IsWrapper<T>::value,"T is not a wrapper type");
typedef typename T::WrappedType RootType;
};
template<class T>
struct GetRootType<T,true> {
typedef typename GetRootType<typename T::WrappedType>::RootType RootType;
};
template<class T>
struct WrapperTraits {
typedef typename GetRootType<T>::RootType RootType;
};
// Test function #######################################
void f(int) {
std::cout<<"int"<<std::endl;
}
// #define ROOT_TYPE_ACCESSOR WrapperTraits // <-- Causes compilation error.
#define ROOT_TYPE_ACCESSOR GetRootType // <-- Compiles without error.
template<class T>
auto f(T) ->
typename std::enable_if<
std::is_same<int,typename ROOT_TYPE_ACCESSOR<T>::RootType>::value
>::type
{
typedef typename ROOT_TYPE_ACCESSOR<T>::RootType RootType;
std::cout<<"Wrapper<...<int>...>"<<std::endl;
f(RootType());
}
int main() {
f(Wrapper<int>());
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgoKLy8gV3JhcHBlciAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCnRlbXBsYXRlPGNsYXNzIFQ+CnN0cnVjdCBXcmFwcGVyIHt0eXBlZGVmIFQgV3JhcHBlZFR5cGU7fTsKCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIEVuYWJsZT12b2lkPgpzdHJ1Y3QgSXNXcmFwcGVyOiBzdGQ6OmZhbHNlX3R5cGUge307Cgp0ZW1wbGF0ZTxjbGFzcyBUPgpzdHJ1Y3QgSXNXcmFwcGVyPFdyYXBwZXI8VD4gPjogc3RkOjp0cnVlX3R5cGUge307CgoKLy8gV3JhcHBlclRyYWl0cyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCnRlbXBsYXRlPAogIGNsYXNzIFQsCiAgYm9vbCBIYXNXcmFwcGVyPQogICAgSXNXcmFwcGVyPFQ+Ojp2YWx1ZSAmJiBJc1dyYXBwZXI8dHlwZW5hbWUgVDo6V3JhcHBlZFR5cGU+Ojp2YWx1ZT4Kc3RydWN0IEdldFJvb3RUeXBlIHsKICBzdGF0aWNfYXNzZXJ0KElzV3JhcHBlcjxUPjo6dmFsdWUsIlQgaXMgbm90IGEgd3JhcHBlciB0eXBlIik7CiAgCiAgdHlwZWRlZiB0eXBlbmFtZSBUOjpXcmFwcGVkVHlwZSBSb290VHlwZTsKfTsKCnRlbXBsYXRlPGNsYXNzIFQ+CnN0cnVjdCBHZXRSb290VHlwZTxULHRydWU+IHsKICB0eXBlZGVmIHR5cGVuYW1lIEdldFJvb3RUeXBlPHR5cGVuYW1lIFQ6OldyYXBwZWRUeXBlPjo6Um9vdFR5cGUgUm9vdFR5cGU7Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUPgpzdHJ1Y3QgV3JhcHBlclRyYWl0cyB7CiAgdHlwZWRlZiB0eXBlbmFtZSBHZXRSb290VHlwZTxUPjo6Um9vdFR5cGUgUm9vdFR5cGU7Cn07CgoKLy8gVGVzdCBmdW5jdGlvbiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCnZvaWQgZihpbnQpIHsKICBzdGQ6OmNvdXQ8PCJpbnQiPDxzdGQ6OmVuZGw7Cn0KCi8vICNkZWZpbmUgUk9PVF9UWVBFX0FDQ0VTU09SIFdyYXBwZXJUcmFpdHMgIC8vIDwtLSBDYXVzZXMgY29tcGlsYXRpb24gZXJyb3IuCiNkZWZpbmUgUk9PVF9UWVBFX0FDQ0VTU09SIEdldFJvb3RUeXBlICAgIC8vIDwtLSBDb21waWxlcyB3aXRob3V0IGVycm9yLgoKdGVtcGxhdGU8Y2xhc3MgVD4KYXV0byBmKFQpIC0+IAogIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPAogICAgc3RkOjppc19zYW1lPGludCx0eXBlbmFtZSBST09UX1RZUEVfQUNDRVNTT1I8VD46OlJvb3RUeXBlPjo6dmFsdWUKICA+Ojp0eXBlCnsKICB0eXBlZGVmIHR5cGVuYW1lIFJPT1RfVFlQRV9BQ0NFU1NPUjxUPjo6Um9vdFR5cGUgUm9vdFR5cGU7CiAgCiAgc3RkOjpjb3V0PDwiV3JhcHBlcjwuLi48aW50Pi4uLj4iPDxzdGQ6OmVuZGw7CiAgZihSb290VHlwZSgpKTsKfQoKCmludCBtYWluKCkgewogIGYoV3JhcHBlcjxpbnQ+KCkpOyAgCiAgcmV0dXJuIDA7IAp9