3

I am trying to check if a function argument passed is unary or not, something like so

template <typename Func>
using EnableIfUnary = std::enable_if_t<std::is_same<
    decltype(std::declval<Func>()(std::declval<const int&>())),
    decltype(std::declval<Func>()(std::declval<const int&>()))>::value>;

template <typename Func, EnableIfUnary<Func>* = nullptr>
void do_something(Func func) { ... }

// and use like so
template <typename Type>
void foo(Type) { cout << "foo(Type)" << endl; }
template <typename Type>
void bar(Type) { typename Type::something{}; }

int main() {
    do_something(foo);
    return 0;
}

Is there a better way to check if a function is unary? My current approach doesn't work when the function pass in (foo() in my example) uses the type in a way that would not work with ints.

In the above case foo is legal and bar isn't, since there is no type named something in int (which is what the enable if checks for)

Curious
  • 20,870
  • 8
  • 61
  • 146
  • Are you going to call it or do something else? `is_invocable` is good for the former, and that can be simulated pretty easily with `void_t` or whatever. – chris Apr 01 '17 at 21:56
  • you could use a variation of this answer to get the number of arguments a function has http://stackoverflow.com/a/9065203/390557 – wreckgar23 Apr 01 '17 at 21:58
  • @chris I am planning on calling it in the `do_something()` function. How will `is_invocable` help with this situation? What argument types do I pass to `is_invocable`? – Curious Apr 01 '17 at 21:58
  • @wreckgar23 I don't think that works when the thing you pass to `function_traits` is a template function? – Curious Apr 01 '17 at 22:01
  • You give it the type of thing you're going to call and what you're going to call it with. It tells you whether that will work. There are other ways to determine arity, even for overloaded or templated functions, but they're more complex than that, so it's well worth it if it's enough. – chris Apr 01 '17 at 22:02
  • @chris Let's say there is a second overload I want to have of the `do_something` function that accepts another argument of a given type – Curious Apr 01 '17 at 22:06
  • @chris nevermind I think i have a solution, but I will still leave the question open so that people can respond if they have an answer – Curious Apr 01 '17 at 22:15
  • 1
    What is a unary function? In C++, such a question on generic callables could require inverting a turing complete program. For example, a variardic function which requires certain properties, collectively, of the type of its arguments. It is easy to answer "can this be called with an X", it is *impossible* to answer "is there an X such that this can be called with just X". With all context (why you want this problem answered) removed from your question, I cannot read your mind and determine which compromise would be suitable. – Yakk - Adam Nevraumont Apr 02 '17 at 00:59

1 Answers1

0
template<typename...>
struct is_unary_function : std::false_type {};

template<typename T, typename R>
struct is_unary_function<R(*)(T)> : std::true_type {};

Live Demo

101010
  • 41,839
  • 11
  • 94
  • 168
  • OP uses function template, I suspect the aim is to check if it has only one template parameter. This doesn't work unless it specializes explicitly the function template and uses the specialization with `is_unary_function`. Moreover, the specialization of `bar` as defined in the question would be invalid and the code wouldn't compile. – skypjack Apr 02 '17 at 07:02