#include <type_traits>
#include <utility>
#include <iostream>
using namespace std;
template <typename T>
class Base
{
protected:
template <typename U>
Base(U&& callable)
{
cout << "called" << endl;
static_assert(
std::is_same<
typename std::remove_reference<decltype(callable())>::type, T
>::value,
"Expression does not evaluate to correct type!");
}
public:
virtual ~Base(void) =default; // Causes error
virtual operator T(void) =0;
Base(Base&&)
{
cout << "move called" << endl;
}
};
template <typename T, typename U>
class Derived : public Base<T>
{
public:
Derived(U&& callable) : Base<T>{std::forward<U>(callable)} {}
operator T(void) override final
{
return {};
}
};
void TakesWrappedInt(Base<int>&&) {}
template <typename U>
auto MakeLazyInt(U&& callable)
{
return Derived<
typename std::remove_reference<decltype(callable())>::type, U>{
std::forward<U>(callable)};
}
int main()
{
TakesWrappedInt(MakeLazyInt([&](){return 3;}));
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8dXRpbGl0eT4KCiNpbmNsdWRlIDxpb3N0cmVhbT4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KY2xhc3MgQmFzZQp7CiAgcHJvdGVjdGVkOgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFU+CiAgICBCYXNlKFUmJiBjYWxsYWJsZSkKICAgIHsKICAgIAljb3V0IDw8ICJjYWxsZWQiIDw8IGVuZGw7CiAgICAgIHN0YXRpY19hc3NlcnQoCiAgICAgICAgICBzdGQ6OmlzX3NhbWU8CiAgICAgICAgICAgICAgdHlwZW5hbWUgc3RkOjpyZW1vdmVfcmVmZXJlbmNlPGRlY2x0eXBlKGNhbGxhYmxlKCkpPjo6dHlwZSwgVAogICAgICAgICAgICA+Ojp2YWx1ZSwKICAgICAgICAgICJFeHByZXNzaW9uIGRvZXMgbm90IGV2YWx1YXRlIHRvIGNvcnJlY3QgdHlwZSEiKTsKICAgIH0KCiAgcHVibGljOgogICAgdmlydHVhbCB+QmFzZSh2b2lkKSA9ZGVmYXVsdDsgLy8gQ2F1c2VzIGVycm9yIAoKICAgIHZpcnR1YWwgb3BlcmF0b3IgVCh2b2lkKSA9MDsKICAgIAogICAgQmFzZShCYXNlJiYpCiAgICB7CiAgICAJCiAgICAJY291dCA8PCAibW92ZSBjYWxsZWQiIDw8IGVuZGw7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVT4KY2xhc3MgRGVyaXZlZCA6IHB1YmxpYyBCYXNlPFQ+CnsKICBwdWJsaWM6CiAgICBEZXJpdmVkKFUmJiBjYWxsYWJsZSkgOiBCYXNlPFQ+e3N0ZDo6Zm9yd2FyZDxVPihjYWxsYWJsZSl9IHt9CgogICAgb3BlcmF0b3IgVCh2b2lkKSBvdmVycmlkZSBmaW5hbAogICAgewogICAgICByZXR1cm4ge307CiAgICB9Cn07Cgp2b2lkIFRha2VzV3JhcHBlZEludChCYXNlPGludD4mJikge30KCnRlbXBsYXRlIDx0eXBlbmFtZSBVPgphdXRvIE1ha2VMYXp5SW50KFUmJiBjYWxsYWJsZSkKewogIHJldHVybiBEZXJpdmVkPAogICAgICAgICAgICB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8ZGVjbHR5cGUoY2FsbGFibGUoKSk+Ojp0eXBlLCBVPnsKICAgICAgc3RkOjpmb3J3YXJkPFU+KGNhbGxhYmxlKX07Cn0KCmludCBtYWluKCkKewogIFRha2VzV3JhcHBlZEludChNYWtlTGF6eUludChbJl0oKXtyZXR1cm4gMzt9KSk7Cn0=