2

I have the following C++ program:

#include <iostream>
#include <functional>

template<class T> void fun(T t) {
    if (t) std::cout << t();
    else std::cout << "no t";
}

int main() {
    std::function<int ()> f;
    fun(f); //The check will evaluate to false

    fun([](){return "hello";});

    int x = 2;
    fun([x](){return x;}); // Compiler error

    return 0;
}

But it doesn't compile. The problem seems to be that a lambda that captures something is converted to a functor object, which in turn is not convertible to bool and therefore cannot be checked for truthfulness.

What's the right way of writing fun so that I can leave main as it is? Is there a way of doing this while keeping things simple (i.e. not specializing fun)?

EDIT: I really only care about checking whether t is true or not, and I am happy to assume that T is a callable type, without checking that explicitly.

Dimitar Asenov
  • 24,986
  • 1
  • 16
  • 20
  • Possible duplicate: [C++ metafunction to determine whether a type is callable](http://stackoverflow.com/questions/5100015/c-metafunction-to-determine-whether-a-type-is-callable) – NathanOliver Jan 08 '16 at 17:42
  • You will find more searching the net: "c++ is_callable" –  Jan 08 '16 at 17:45
  • I read that other question and while it is similar, I don't think it's quite the same. That question is really about testing whether something is callable. In my case, I know that T is callable type, but I want to know whether an actual callable object was supplied or not. For example, in the code above, f is callable, but "empty". I'll edit the question to make this clearer. – Dimitar Asenov Jan 11 '16 at 09:56

1 Answers1

2

You're going to need to do some kind of specialization or overloading, but you can at least separate out the work into a predicate function:

template<class T>
typename std::enable_if<
  std::is_constructible<bool, T>::value, bool>::type
okToCall(T&&t) { return static_cast<bool>(t); }
template<class T>
constexpr typename std::enable_if<
  !std::is_constructible<bool, T>::value, bool>::type
okToCall(T&&) { return true; }

template<class T> void fun(T t) {
    if (okToCall(t)) std::cout << t();
    else std::cout << "no t";
}

Example: http://coliru.stacked-crooked.com/a/a08468965ed6d54e

The only real difficulty is working out what to call the okToCall predicate function - what it's really doing is returning true if T is not convertible to bool, but its value converted to bool if it is convertible.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • I suppose this answers the question OP asks in the body, but not in the title. The assumption is that any old pointer that can be converted to `true` is callable, which is false. `int b = 42; int* a = &b; fun(a);` – AndyG Jan 08 '16 at 21:05
  • @AndyG You are right, but actually I only care about checking truthfulness, and am happy to assume that the type itself is callable. I edited the question to make this clear. – Dimitar Asenov Jan 11 '16 at 10:02
  • @ecatmur Thanks. This does answer my question, though I was hoping that there would be a smaller solution, or that something like `okToCall` would have been built-in in the standard library. – Dimitar Asenov Jan 11 '16 at 10:04
  • @Mitko yeah, sorry - the language isn't particularly good at this kind of thing currently. Some kind of static if facility (e.g. n4461, or http://baptiste-wicht.com/posts/2015/07/simulate-static_if-with-c11c14.html) would allow coding it without overloads. – ecatmur Jan 11 '16 at 10:10