#include <iostream>
template <typename R, typename P, typename = typename R::base_type>
struct inherit_base_pattern : public virtual P { };
template <typename R, typename P>
struct inherit_base_pattern<R, P, R> { };
template <int I1, int I2>
struct adder { typedef adder base_type; };
template <int I1, int I2>
struct adder1 : public adder<I1, I2> { typedef adder<I1, I2> base_type; };
template <int I1, int I2>
struct adder2 : public adder<I1, I2> { typedef adder<I1, I2> base_type; };
template <int I1, int I2>
struct adder3 : public adder2<I1, I2> { typedef adder2<I1, I2> base_type; };
template <typename A, int I>
struct fusedmultiplyadder
: public inherit_base_pattern< A, fusedmultiplyadder<typename A::base_type, I> >
{ typedef fusedmultiplyadder base_type; };
template <typename A, int I>
struct fusedmultiplyadder1
: public virtual fusedmultiplyadder<A, I>,
public inherit_base_pattern< A, fusedmultiplyadder1<typename A::base_type, I> >
{ typedef fusedmultiplyadder<A, I> base_type; };
template <int i1, int i2, int i3>
void foo(fusedmultiplyadder<adder<i1, i2>, i3>)
{
std::cout << "fma: " << i1 << ", " << i2 << ", " << i3 << std::endl;
}
int main()
{
fusedmultiplyadder<adder1<2, 3>, 4> fma1;
foo(fma1);
fusedmultiplyadder<adder2<2, 3>, 4> fma2;
foo(fma2);
fusedmultiplyadder<adder3<2, 3>, 4> fma3;
foo(fma3);
fusedmultiplyadder1<adder2<2, 3>, 4> fma4;
foo(fma4);
fusedmultiplyadder1<adder3<2, 3>, 4> fma5;
foo(fma5);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lIFIsIHR5cGVuYW1lIFAsIHR5cGVuYW1lID0gdHlwZW5hbWUgUjo6YmFzZV90eXBlPgpzdHJ1Y3QgaW5oZXJpdF9iYXNlX3BhdHRlcm4gOiBwdWJsaWMgdmlydHVhbCBQIHsgfTsKdGVtcGxhdGUgPHR5cGVuYW1lIFIsIHR5cGVuYW1lIFA+CnN0cnVjdCBpbmhlcml0X2Jhc2VfcGF0dGVybjxSLCBQLCBSPiB7IH07CiAgIAp0ZW1wbGF0ZSA8aW50IEkxLCBpbnQgSTI+CnN0cnVjdCBhZGRlciB7IHR5cGVkZWYgYWRkZXIgYmFzZV90eXBlOyB9OwoKdGVtcGxhdGUgPGludCBJMSwgaW50IEkyPgpzdHJ1Y3QgYWRkZXIxIDogcHVibGljIGFkZGVyPEkxLCBJMj4geyB0eXBlZGVmIGFkZGVyPEkxLCBJMj4gYmFzZV90eXBlOyB9OwogCnRlbXBsYXRlIDxpbnQgSTEsIGludCBJMj4Kc3RydWN0IGFkZGVyMiA6IHB1YmxpYyBhZGRlcjxJMSwgSTI+IHsgdHlwZWRlZiBhZGRlcjxJMSwgSTI+IGJhc2VfdHlwZTsgfTsKCnRlbXBsYXRlIDxpbnQgSTEsIGludCBJMj4Kc3RydWN0IGFkZGVyMyA6IHB1YmxpYyBhZGRlcjI8STEsIEkyPiB7IHR5cGVkZWYgYWRkZXIyPEkxLCBJMj4gYmFzZV90eXBlOyB9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEEsIGludCBJPgpzdHJ1Y3QgZnVzZWRtdWx0aXBseWFkZGVyCiAgIDogcHVibGljIGluaGVyaXRfYmFzZV9wYXR0ZXJuPCBBLCBmdXNlZG11bHRpcGx5YWRkZXI8dHlwZW5hbWUgQTo6YmFzZV90eXBlLCBJPiA+CnsgdHlwZWRlZiBmdXNlZG11bHRpcGx5YWRkZXIgYmFzZV90eXBlOyB9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEEsIGludCBJPgpzdHJ1Y3QgZnVzZWRtdWx0aXBseWFkZGVyMQogICA6IHB1YmxpYyB2aXJ0dWFsIGZ1c2VkbXVsdGlwbHlhZGRlcjxBLCBJPiwKICAgcHVibGljIGluaGVyaXRfYmFzZV9wYXR0ZXJuPCBBLCBmdXNlZG11bHRpcGx5YWRkZXIxPHR5cGVuYW1lIEE6OmJhc2VfdHlwZSwgST4gPgp7IHR5cGVkZWYgZnVzZWRtdWx0aXBseWFkZGVyPEEsIEk+IGJhc2VfdHlwZTsgfTsKCnRlbXBsYXRlIDxpbnQgaTEsIGludCBpMiwgaW50IGkzPgp2b2lkIGZvbyhmdXNlZG11bHRpcGx5YWRkZXI8YWRkZXI8aTEsIGkyPiwgaTM+KQp7CiAgIHN0ZDo6Y291dCA8PCAiZm1hOiAiIDw8IGkxIDw8ICIsICIgPDwgaTIgPDwgIiwgIiA8PCBpMyA8PCBzdGQ6OmVuZGw7Cn0KIAppbnQgbWFpbigpCnsKICAgZnVzZWRtdWx0aXBseWFkZGVyPGFkZGVyMTwyLCAzPiwgND4gZm1hMTsKICAgZm9vKGZtYTEpOwogICBmdXNlZG11bHRpcGx5YWRkZXI8YWRkZXIyPDIsIDM+LCA0PiBmbWEyOwogICBmb28oZm1hMik7CiAgIGZ1c2VkbXVsdGlwbHlhZGRlcjxhZGRlcjM8MiwgMz4sIDQ+IGZtYTM7CiAgIGZvbyhmbWEzKTsKICAgZnVzZWRtdWx0aXBseWFkZGVyMTxhZGRlcjI8MiwgMz4sIDQ+IGZtYTQ7CiAgIGZvbyhmbWE0KTsKICAgZnVzZWRtdWx0aXBseWFkZGVyMTxhZGRlcjM8MiwgMz4sIDQ+IGZtYTU7CiAgIGZvbyhmbWE1KTsKICAgcmV0dXJuIDA7Cn0=