检查模板参数是否为“真正的”可调用对象的正确方法是什么?

时间:2016-01-08 17:38:28

标签: c++ templates lambda

我有以下C ++程序:

#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;
}

但它没有编译。问题似乎是捕获某些东西的lambda被转换为仿函数对象,而该仿函数对象又无法转换为bool,因此无法检查其真实性。

fun的正确方法是什么,以便我可以保留main原样?有没有办法在保持简单的同时做到这一点(即不专门化fun)?

编辑:我真的只关心检查t是否为真,我很乐意假设T是一个可调用的类型,而没有明确检查

1 个答案:

答案 0 :(得分:2)

您需要进行某种专业化或重载,但您至少可以将工作分离为谓词函数:

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";
}

示例:http://coliru.stacked-crooked.com/a/a08468965ed6d54e

唯一真正的困难是确定调用okToCall谓词函数的内容 - 如果true ,它正在做的是返回T em>可转换为bool,但如果 可转换,则其值转换为bool