Created
May 10, 2016 15:20
-
-
Save aguinet/791e98368946b9bc5d3e45ab7a2441f2 to your computer and use it in GitHub Desktop.
Helper templates to easily check whether a function type has the right signature (without std::function)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) 2016 Adrien Guinet | |
// Helper templates to easily check whether a function type has the right | |
// signature (without std::function). | |
// If you have std::function, simply do | |
// | |
// template <class F, class R, class... Args> | |
// struct has_sign: | |
// public std::is_convertible<F, std::function<R(Args...)>> | |
// { }; | |
// | |
// Any better way to do this is appreciated :) | |
// You can use it freely as long as the original copyright is mentioned. | |
#include <string> | |
#include <type_traits> | |
#include <functional> | |
template <class F, bool, class R, class... Args> | |
struct has_sign_impl; | |
template <class F, class R, class... Args> | |
struct has_sign_impl<F, false, R, Args...> | |
{ | |
using func_type = decltype(&F::operator()); | |
static constexpr bool value = | |
std::is_convertible<func_type, R(F::*)(Args...)>::value | | |
std::is_convertible<func_type, R(F::*)(Args...) const>::value; | |
}; | |
template <class F, class R, class... Args> | |
struct has_sign_impl<F, true, R, Args...>: | |
public std::is_convertible<F, R(*)(Args...)> | |
{ }; | |
template <class F, class R, class... Args> | |
struct has_sign | |
{ | |
using func_type = typename std::decay<F>::type; | |
static constexpr bool value = has_sign_impl<func_type, std::is_pointer<func_type>::value, R, Args...>::value; | |
}; | |
int test(std::string) { return 0; } | |
int test2(int i) { return 0; } | |
struct MyF | |
{ | |
int operator()(std::string) { return _i; } | |
int _i; | |
}; | |
struct MyF2 | |
{ | |
int operator()(int a) const { return a+_i; } | |
int _i; | |
}; | |
template <class F> | |
bool is_ok(F f) | |
{ | |
return has_sign<F, int, std::string>::value; | |
} | |
int main(int argc, char** argv) | |
{ | |
MyF myf; | |
MyF2 myf2; | |
printf("should be ok\n"); | |
printf("%d\n", is_ok(test)); | |
printf("%d\n", is_ok([](std::string) -> int { return 1; })); | |
printf("%d\n", is_ok(myf)); | |
printf("%d\n", is_ok([argc](std::string) -> int { return argc+1; })); | |
printf("should fail\n"); | |
printf("%d\n", is_ok(test2)); | |
printf("%d\n", is_ok([](short) -> short { return 1; })); | |
printf("%d\n", is_ok(myf2)); | |
printf("%d\n", is_ok([argc](short) -> short { return argc+1; })); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What about