如何在编译时检查是否存在可以使用特定的一组参数调用的函数? [英] How to check at compile-time if a function that can be called with a specific set of arguments exists?

查看:96
本文介绍了如何在编译时检查是否存在可以使用特定的一组参数调用的函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这与检查是否定义特定功能不同。在这里,为了检查返回 true ,函数必须被定义,并且传递特定类型的参数应该导致有效的调用。

This is different from checking if a specific function is defined. Here, for this check to return true, the function has to be defined and passing the arguments of a certain type should result in a valid call.

示例:对于函数 f 和类型 T&& 的参数,如果 f 是一个有效的函数,它可以直接或通过隐式转换接受一个参数,那么检查应该返回 true T&&

Example: for a function f and an argument of type T &&, the check should return true if f is a valid function that accepts—either directly or through implicit conversion—an argument of type T &&.

void f(int &) {};

int main(int argc, char **av)
{
    isFunctionCallable<int>(f); // true because `int i; f(i);` is valid.
    isFunctionCallable<int &&>(f); // false because `int i; f(std::move(i));` is invalid.
    return 0;
}

请注意参数和参数 a href =https://stackoverflow.com/a/1788926/1640404>这个答案。

Please note the distinction between "arguments" and "parameters" as explained in this answer.

推荐答案

使用C ++ 11,可以使用SFINAE, decltype std :: declval

Making use of C++11, this can be done using a mixture of SFINAE, decltype and std::declval.

template<typename ...>
struct Bool
{ using type = bool; };

template<typename ... T_Dummies>
using BoolT = typename Bool<T_Dummies ...>::type;


template<typename T>
struct DeclvalType
{
    using type = typename std::conditional<
        std::is_rvalue_reference<T>::value,
        T,
        T &
    >::type;
};

template<typename T>
using DeclvalTypeT = typename DeclvalType<T>::type;


template<typename T>
struct ExtractFunction;

template<typename T_Return, typename ... T_Args>
struct ExtractFunction<T_Return(T_Args ...)>
{ using type = T_Return(T_Args ...); };

template<typename T_Return, typename ... T_Args>
struct ExtractFunction<T_Return(*)(T_Args ...)>
{ using type = T_Return(T_Args ...); };

template<typename T, typename T_Return, typename ... T_Args>
struct ExtractFunction<T_Return(T::*)(T_Args ...)>
{ using type = T_Return(T_Args ...); };

template<typename T, typename T_Return, typename ... T_Args>
struct ExtractFunction<T_Return(T::*)(T_Args ...) const>
{ using type = T_Return(T_Args ...); };

template<typename T>
using ExtractFunctionT = typename ExtractFunction<T>::type;


template<typename ... T, typename T_Function>
constexpr auto
impl(T_Function function) ->
    BoolT<decltype(
        std::declval<ExtractFunctionT<T_Function>>()
            (std::declval<DeclvalTypeT<T>>() ...)
    )>
{ return true; }

template<typename ... T>
constexpr bool
impl(...)
{ return false; }


template<typename ... T, typename T_Function>
constexpr bool
isFunctionCallable(T_Function function)
{ return impl<T ...>(function); }

借助更多代码(可在 this Gist ),可以输出表格,显示可以传递哪种参数类型的参数。

With the help of some more code (available in this Gist), it is possible to output tables showing what type of arguments can be passed to what type of parameters.

using T = Default (empty struct with implicit constructors):

  +--------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
  |                                |                                                                                                                                 |
  |        Function signature      |                                                          Argument type                                                          |
  |                                |                                                                                                                                 |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |                                |  T  |  const T  |   volatile T  |   const volatile T  |  T &  |  const T &  |   volatile T &  |   const volatile T &  |   T &&  |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T)                   |  x  |     x     |               |                     |   x   |      x      |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const T)             |  x  |     x     |               |                     |   x   |      x      |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(volatile T)          |  x  |     x     |               |                     |   x   |      x      |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const volatile T)    |  x  |     x     |               |                     |   x   |      x      |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T &)                 |  x  |           |               |                     |   x   |             |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const T &)           |  x  |     x     |               |                     |   x   |      x      |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(volatile T &)        |  x  |           |       x       |                     |   x   |             |        x        |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const volatile T &)  |  x  |     x     |       x       |          x          |   x   |      x      |        x        |           x           |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T &&)                |     |           |               |                     |       |             |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+


using T = NonCopiable:

  +--------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
  |                                |                                                                                                                                 |
  |        Function signature      |                                                          Argument type                                                          |
  |                                |                                                                                                                                 |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |                                |  T  |  const T  |   volatile T  |   const volatile T  |  T &  |  const T &  |   volatile T &  |   const volatile T &  |   T &&  |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T)                   |     |           |               |                     |       |             |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const T)             |     |           |               |                     |       |             |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(volatile T)          |     |           |               |                     |       |             |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const volatile T)    |     |           |               |                     |       |             |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T &)                 |  x  |           |               |                     |   x   |             |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const T &)           |  x  |     x     |               |                     |   x   |      x      |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(volatile T &)        |  x  |           |       x       |                     |   x   |             |        x        |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const volatile T &)  |  x  |     x     |       x       |          x          |   x   |      x      |        x        |           x           |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T &&)                |     |           |               |                     |       |             |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+


using T = NonMovable:

  +--------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
  |                                |                                                                                                                                 |
  |        Function signature      |                                                          Argument type                                                          |
  |                                |                                                                                                                                 |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |                                |  T  |  const T  |   volatile T  |   const volatile T  |  T &  |  const T &  |   volatile T &  |   const volatile T &  |   T &&  |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T)                   |  x  |     x     |               |                     |   x   |      x      |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const T)             |  x  |     x     |               |                     |   x   |      x      |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(volatile T)          |  x  |     x     |               |                     |   x   |      x      |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const volatile T)    |  x  |     x     |               |                     |   x   |      x      |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T &)                 |  x  |           |               |                     |   x   |             |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const T &)           |  x  |     x     |               |                     |   x   |      x      |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(volatile T &)        |  x  |           |       x       |                     |   x   |             |        x        |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const volatile T &)  |  x  |     x     |       x       |          x          |   x   |      x      |        x        |           x           |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T &&)                |     |           |               |                     |       |             |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+


using T = NonCopiableNonMovable:

  +--------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
  |                                |                                                                                                                                 |
  |        Function signature      |                                                          Argument type                                                          |
  |                                |                                                                                                                                 |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |                                |  T  |  const T  |   volatile T  |   const volatile T  |  T &  |  const T &  |   volatile T &  |   const volatile T &  |   T &&  |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T)                   |     |           |               |                     |       |             |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const T)             |     |           |               |                     |       |             |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(volatile T)          |     |           |               |                     |       |             |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const volatile T)    |     |           |               |                     |       |             |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T &)                 |  x  |           |               |                     |   x   |             |                 |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const T &)           |  x  |     x     |               |                     |   x   |      x      |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(volatile T &)        |  x  |           |       x       |                     |   x   |             |        x        |                       |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(const volatile T &)  |  x  |     x     |       x       |          x          |   x   |      x      |        x        |           x           |         |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
  |  function(T &&)                |     |           |               |                     |       |             |                 |                       |    x    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+

我们可以从这些表中推断出 T 类型的参数不能传递给一个函数,该函数需要 T&& 作为参数。或者函数(T&& amp;& amp; amp; amp;& amp; amp; amp; amp; amp;& amp; amp;& amp; amp; amp; amp; ampcc)只接受类型为code> T&& 的参数。

We can for example deduce from these tables that an argument of type T can't be passed to a function that takes T && as parameter. Or that function(T &&) only accepts arguments of type T &&.

请注意,删除副本和/或移动构造函数会降低可能性,因为参数不能隐式转换。

Note how deleting the copy and/or the move constructor reduce the possibilities since the arguments can't be converted implicitly anymore.

编辑:

增加了对成员函数的支持,感谢@ hvd。

Added support for member functions, thanks to @hvd.

这篇关于如何在编译时检查是否存在可以使用特定的一组参数调用的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆