#include <iostream>
#include <type_traits>
#include <functional>
////////////////////////////////////////////////////////////////////////////////
// Detection idiom, from C++ Library fundamentals extension in N4436
namespace std {
namespace experimental {
// A void_t implementation that works with gcc-4.9 (workaround for bug 64395
// From: http://stackoverflow.com/questions/35753920/why-does-the-void-t-detection-idiom-not-work-with-gcc-4-9
namespace _void_t_impl {
template <class... >
struct make_void { using type = void; };
} // end namepace _void_t_impl
template <class... T>
using void_t = typename _void_t_impl::make_void<T...>::type;
template <
class Default,
class _always_void,
template <class...> class Op,
class... Args
>
struct detector {
constexpr static auto value = false;
using type = Default;
};
// specialization recognizes and handles only types supporting Op
template <
class Default,
template <class...> class Op,
class... Args
>
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
constexpr static auto value = true;
using type = Op<Args...>;
};
struct nonesuch {
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
constexpr static auto value = false;
};
template <template <class...> class Op, class... Args>
using is_detected = detector<nonesuch, void, Op, Args...>;
template <template <class...> class Op, class... Args>
using detected_t = typename is_detected<Op, Args...>::type;
template <class Default, template <class...> class Op, class... Args>
using detected_or = detector<Default, void, Op, Args...>;
template <class Default, template <class...> class Op, class... Args>
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
template <class Expected, template<class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template <class To, template <class...> class Op, class... Args>
using is_detected_convertible = std::is_convertible<detected_t<Op, Args...>, To>;
} // end namespace experimental
} // end namespace std
////////////////////////////////////////////////////////////////////////////////
using namespace std;
using namespace std::experimental;
static constexpr auto max_num_args = 127;
struct any {
template <typename T,
typename = enable_if_t<
not is_same<T, remove_reference_t<T>>::value
>
>
operator T();
template <typename T,
typename = enable_if_t<
is_same<T, remove_reference_t<T>>::value
>
>
operator T&();
template <typename T,
typename = enable_if_t<
is_same<T, remove_reference_t<T>>::value
>
>
operator T&&();
};
template <typename F, typename... Args>
using callable_archetype = decltype( declval<F>()(declval<Args>()...) );
template <typename F, typename... Args>
using is_callable_with_args = is_detected<callable_archetype, F, Args...>;
template <typename F, size_t I = 0, typename... Args>
struct count_args
: conditional<
is_callable_with_args<F, Args...>::value,
integral_constant<size_t, I>,
count_args<F, I+1, Args..., any>
>::type::type
{ };
template <typename F, typename... Args>
struct count_args<F, max_num_args, Args...> : integral_constant<size_t, max_num_args> { };
// Some example cases
void foo(int i, int j) { }
struct bar {
void operator()(std::string const&, std::ostream const&, int) const { }
};
void baz(std::string&, const std::string&) { }
int main(int argc, char** argv) {
cout << count_args<decltype(foo)>::value << endl; // Should be 2
cout << count_args<bar>::value << endl; // should be 3
cout << count_args<decltype(baz)>::value << endl; // fails because of lvalue reference!
}
CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vIERldGVjdGlvbiBpZGlvbSwgZnJvbSBDKysgTGlicmFyeSBmdW5kYW1lbnRhbHMgZXh0ZW5zaW9uIGluIE40NDM2CgpuYW1lc3BhY2Ugc3RkIHsgCm5hbWVzcGFjZSBleHBlcmltZW50YWwgewoKLy8gQSB2b2lkX3QgaW1wbGVtZW50YXRpb24gdGhhdCB3b3JrcyB3aXRoIGdjYy00LjkgKHdvcmthcm91bmQgZm9yIGJ1ZyA2NDM5NQovLyBGcm9tOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM1NzUzOTIwL3doeS1kb2VzLXRoZS12b2lkLXQtZGV0ZWN0aW9uLWlkaW9tLW5vdC13b3JrLXdpdGgtZ2NjLTQtOQpuYW1lc3BhY2UgX3ZvaWRfdF9pbXBsIHsKCnRlbXBsYXRlIDxjbGFzcy4uLiA+CnN0cnVjdCBtYWtlX3ZvaWQgeyB1c2luZyB0eXBlID0gdm9pZDsgfTsKCn0gLy8gZW5kIG5hbWVwYWNlIF92b2lkX3RfaW1wbAoKdGVtcGxhdGUgPGNsYXNzLi4uIFQ+CnVzaW5nIHZvaWRfdCA9IHR5cGVuYW1lIF92b2lkX3RfaW1wbDo6bWFrZV92b2lkPFQuLi4+Ojp0eXBlOwoKdGVtcGxhdGUgPAogIGNsYXNzIERlZmF1bHQsCiAgY2xhc3MgX2Fsd2F5c192b2lkLAogIHRlbXBsYXRlIDxjbGFzcy4uLj4gY2xhc3MgT3AsCiAgY2xhc3MuLi4gQXJncwo+CnN0cnVjdCBkZXRlY3RvciB7CiAgY29uc3RleHByIHN0YXRpYyBhdXRvIHZhbHVlID0gZmFsc2U7CiAgdXNpbmcgdHlwZSA9IERlZmF1bHQ7Cn07CgovLyBzcGVjaWFsaXphdGlvbiByZWNvZ25pemVzIGFuZCBoYW5kbGVzIG9ubHkgdHlwZXMgc3VwcG9ydGluZyBPcAp0ZW1wbGF0ZSA8CiAgY2xhc3MgRGVmYXVsdCwKICB0ZW1wbGF0ZSA8Y2xhc3MuLi4+IGNsYXNzIE9wLAogIGNsYXNzLi4uIEFyZ3MKPgpzdHJ1Y3QgZGV0ZWN0b3I8RGVmYXVsdCwgdm9pZF90PE9wPEFyZ3MuLi4+PiwgT3AsIEFyZ3MuLi4+IHsKICBjb25zdGV4cHIgc3RhdGljIGF1dG8gdmFsdWUgPSB0cnVlOwogIHVzaW5nIHR5cGUgPSBPcDxBcmdzLi4uPjsKfTsKCnN0cnVjdCBub25lc3VjaCB7CiAgbm9uZXN1Y2goKSA9IGRlbGV0ZTsKICB+bm9uZXN1Y2goKSA9IGRlbGV0ZTsKICBub25lc3VjaChub25lc3VjaCBjb25zdCYpID0gZGVsZXRlOwogIHZvaWQgb3BlcmF0b3I9KG5vbmVzdWNoIGNvbnN0JikgPSBkZWxldGU7CiAgY29uc3RleHByIHN0YXRpYyBhdXRvIHZhbHVlID0gZmFsc2U7Cn07Cgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPGNsYXNzLi4uPiBjbGFzcyBPcCwgY2xhc3MuLi4gQXJncz4KdXNpbmcgaXNfZGV0ZWN0ZWQgPSBkZXRlY3Rvcjxub25lc3VjaCwgdm9pZCwgT3AsIEFyZ3MuLi4+OwoKdGVtcGxhdGUgPHRlbXBsYXRlIDxjbGFzcy4uLj4gY2xhc3MgT3AsIGNsYXNzLi4uIEFyZ3M+CnVzaW5nIGRldGVjdGVkX3QgPSB0eXBlbmFtZSBpc19kZXRlY3RlZDxPcCwgQXJncy4uLj46OnR5cGU7Cgp0ZW1wbGF0ZSA8Y2xhc3MgRGVmYXVsdCwgdGVtcGxhdGUgPGNsYXNzLi4uPiBjbGFzcyBPcCwgY2xhc3MuLi4gQXJncz4KdXNpbmcgZGV0ZWN0ZWRfb3IgPSBkZXRlY3RvcjxEZWZhdWx0LCB2b2lkLCBPcCwgQXJncy4uLj47Cgp0ZW1wbGF0ZSA8Y2xhc3MgRGVmYXVsdCwgdGVtcGxhdGUgPGNsYXNzLi4uPiBjbGFzcyBPcCwgY2xhc3MuLi4gQXJncz4KdXNpbmcgZGV0ZWN0ZWRfb3JfdCA9IHR5cGVuYW1lIGRldGVjdGVkX29yPERlZmF1bHQsIE9wLCBBcmdzLi4uPjo6dHlwZTsKCnRlbXBsYXRlIDxjbGFzcyBFeHBlY3RlZCwgdGVtcGxhdGU8Y2xhc3MuLi4+IGNsYXNzIE9wLCBjbGFzcy4uLiBBcmdzPgp1c2luZyBpc19kZXRlY3RlZF9leGFjdCA9IHN0ZDo6aXNfc2FtZTxFeHBlY3RlZCwgZGV0ZWN0ZWRfdDxPcCwgQXJncy4uLj4+OwoKdGVtcGxhdGUgPGNsYXNzIFRvLCB0ZW1wbGF0ZSA8Y2xhc3MuLi4+IGNsYXNzIE9wLCBjbGFzcy4uLiBBcmdzPgp1c2luZyBpc19kZXRlY3RlZF9jb252ZXJ0aWJsZSA9IHN0ZDo6aXNfY29udmVydGlibGU8ZGV0ZWN0ZWRfdDxPcCwgQXJncy4uLj4sIFRvPjsKCn0gLy8gZW5kIG5hbWVzcGFjZSBleHBlcmltZW50YWwKfSAvLyBlbmQgbmFtZXNwYWNlIHN0ZAoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnVzaW5nIG5hbWVzcGFjZSBzdGQ6OmV4cGVyaW1lbnRhbDsKCnN0YXRpYyBjb25zdGV4cHIgYXV0byBtYXhfbnVtX2FyZ3MgPSAxMjc7CgpzdHJ1Y3QgYW55IHsKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwKICAgIHR5cGVuYW1lID0gZW5hYmxlX2lmX3Q8CiAgICAgIG5vdCBpc19zYW1lPFQsIHJlbW92ZV9yZWZlcmVuY2VfdDxUPj46OnZhbHVlCiAgICA+CiAgPgogIG9wZXJhdG9yIFQoKTsKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwKICAgIHR5cGVuYW1lID0gZW5hYmxlX2lmX3Q8CiAgICAgIGlzX3NhbWU8VCwgcmVtb3ZlX3JlZmVyZW5jZV90PFQ+Pjo6dmFsdWUKICAgID4KICA+CiAgb3BlcmF0b3IgVCYoKTsKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwKICAgIHR5cGVuYW1lID0gZW5hYmxlX2lmX3Q8CiAgICAgIGlzX3NhbWU8VCwgcmVtb3ZlX3JlZmVyZW5jZV90PFQ+Pjo6dmFsdWUKICAgID4KICA+CiAgb3BlcmF0b3IgVCYmKCk7Cn07CgoKdGVtcGxhdGUgPHR5cGVuYW1lIEYsIHR5cGVuYW1lLi4uIEFyZ3M+CnVzaW5nIGNhbGxhYmxlX2FyY2hldHlwZSA9IGRlY2x0eXBlKCBkZWNsdmFsPEY+KCkoZGVjbHZhbDxBcmdzPigpLi4uKSApOwp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgdHlwZW5hbWUuLi4gQXJncz4KdXNpbmcgaXNfY2FsbGFibGVfd2l0aF9hcmdzID0gaXNfZGV0ZWN0ZWQ8Y2FsbGFibGVfYXJjaGV0eXBlLCBGLCBBcmdzLi4uPjsKCnRlbXBsYXRlIDx0eXBlbmFtZSBGLCBzaXplX3QgSSA9IDAsICB0eXBlbmFtZS4uLiBBcmdzPgpzdHJ1Y3QgY291bnRfYXJncwogIDogY29uZGl0aW9uYWw8CiAgICAgIGlzX2NhbGxhYmxlX3dpdGhfYXJnczxGLCBBcmdzLi4uPjo6dmFsdWUsCiAgICAgIGludGVncmFsX2NvbnN0YW50PHNpemVfdCwgST4sCiAgICAgIGNvdW50X2FyZ3M8RiwgSSsxLCBBcmdzLi4uLCBhbnk+CiAgICA+Ojp0eXBlOjp0eXBlCnsgfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBGLCB0eXBlbmFtZS4uLiBBcmdzPgpzdHJ1Y3QgY291bnRfYXJnczxGLCBtYXhfbnVtX2FyZ3MsIEFyZ3MuLi4+IDogaW50ZWdyYWxfY29uc3RhbnQ8c2l6ZV90LCBtYXhfbnVtX2FyZ3M+IHsgfTsKCi8vIFNvbWUgZXhhbXBsZSBjYXNlcwoKdm9pZCBmb28oaW50IGksIGludCBqKSB7IH0Kc3RydWN0IGJhciB7CiAgdm9pZCBvcGVyYXRvcigpKHN0ZDo6c3RyaW5nIGNvbnN0Jiwgc3RkOjpvc3RyZWFtIGNvbnN0JiwgaW50KSBjb25zdCB7IH0KfTsKdm9pZCBiYXooc3RkOjpzdHJpbmcmLCBjb25zdCBzdGQ6OnN0cmluZyYpIHsgfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqKiBhcmd2KSB7CiAgY291dCA8PCBjb3VudF9hcmdzPGRlY2x0eXBlKGZvbyk+Ojp2YWx1ZSA8PCBlbmRsOyAvLyBTaG91bGQgYmUgMiAKICBjb3V0IDw8IGNvdW50X2FyZ3M8YmFyPjo6dmFsdWUgPDwgZW5kbDsgLy8gc2hvdWxkIGJlIDMKICBjb3V0IDw8IGNvdW50X2FyZ3M8ZGVjbHR5cGUoYmF6KT46OnZhbHVlIDw8IGVuZGw7IC8vIGZhaWxzIGJlY2F1c2Ugb2YgbHZhbHVlIHJlZmVyZW5jZSEKfQoK