Skip to content

Instantly share code, notes, and snippets.

@insooth
Last active September 6, 2017 14:12
Show Gist options
  • Save insooth/4d9339a0e8b1127f648c2e796952efc3 to your computer and use it in GitHub Desktop.
Save insooth/4d9339a0e8b1127f648c2e796952efc3 to your computer and use it in GitHub Desktop.
Recovering associated type through tag dispatch
// Based on: http://alexpolt.github.io/type-loophole.html
// LIVE: http://coliru.stacked-crooked.com/a/fda3b5b343980e02
#include <iostream>
#include <type_traits>
#include <utility>
template<class T, class Tag> T foo(Tag);
template<class T, class Tag> T baz(Tag);
// A is a wrapper used to set the body and argument of foo
template<class T, class Tag>
struct A
{
friend T foo<>(Tag);
friend auto bar(Tag) { return T{}; };
// Tag and T are bound upon instantiation of A
// result type (auto) is set call to this function
// -- it is deduced from the expression in the function body
// auto in result type does something like this (default params not allowed in friend templates):
// template<class RR = R> friend RR bar(Tag);
friend T baz<>(Tag);
};
struct X {};
auto bar(X); // forward declaration to expose this function outside wrapper A
int baz(X); // stores the relation between X and int
template class A<int, X>; // generate A::foo(Tag) and associate it with A<T, Tag>
int main()
{
static_assert(std::is_same_v<int, decltype(foo<int>(X{}))>);
// static_assert(std::is_same_v<int, decltype(foo(X{}))>); // error: couldn't deduce template parameter 'T'
static_assert(std::is_same_v<int, decltype(bar(X{}))>);
static_assert(std::is_same_v<int, decltype(baz(X{}))>);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment