如果可以使用一组特定参数调用的函数存在,如何在编译时检查?

Chr*_*erC 4 c++ templates function compile-time

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

示例:对于函数f和类型的参数,如果是直接或通过隐式转换(类型的参数)接受的有效函数,T &&则应返回检查.truefT &&

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意本答案中解释的"参数"和"参数"之间的区别.

Chr*_*erC 8

利用C++ 11,可以使用SFINAE decltypestd::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); }
Run Code Online (Sandbox Code Playgroud)

借助更多代码(在本Gist中可用),可以输出表格,显示可以将哪种类型的参数传递给哪种类型的参数.

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    |
  +--------------------------------+-----+-----------+---------------+---------------------+-------+-------------+-----------------+-----------------------+---------+
Run Code Online (Sandbox Code Playgroud)

例如,我们可以从这些表中推断出类型的参数T不能传递给T &&作为参数的函数.或者function(T &&)只接受类型的参数T &&.

请注意删除副本和/或移动构造函数如何减少可能性,因为参数不能再隐式转换.

编辑:

由于@hvd,增加了对成员函数的支持.