用decltype()声明一个函数签名

时间:2014-01-10 21:49:20

标签: c++ c++11 definition decltype

是否可以声明函数bar与函数foo具有相同的签名?

int foo(int a)
{
    return 0; 
}

decltype(foo) bar
{
    return 1;
} //imaginary syntax

4 个答案:

答案 0 :(得分:2)

我认为同样适用于typedef和别名:您可以使用decltype 声明一个函数,但不能定义它:

int foo();

decltype(foo) bar;

int foo()
{
    return bar();
}

int bar() { return 0; }

被clang ++ 3.5和g ++ 4.8.1

接受

[dcl.fct.def.general] / 2禁止(语法上)没有括号的函数的定义:

  

函数定义中的声明符应具有

形式      

D1 ( parameter-declaration-clause ) cv-qualifier-seq opt   ref-qualifier opt exception-specification opt attribute-specifier-seq opt trailing-return-type opt

     

如8.3.5中所述。

答案 1 :(得分:2)

您可以使用可变参数模板来定义与任何函数具有相同签名的函数:

#include <iostream>

int foo(char const *blah) { return 0; }

template<typename... Args>
auto bar(Args ... args) -> decltype(foo(args...))
{
    return 1; 
}

int main() {
    std::cout << foo("test") << std::endl;
    std::cout << bar("test") << std::endl;
    return 0;
}

这也可以稍微修改一下,将“foo”作为第一个模板参数传递,这样你就可以使用带有许多不同“foo”的相同“bar”:

template<typename Func, typename... Args>
auto bar(Func f, Args ... args) -> decltype(f(args...))
{
    return 1; 
}

int baz(double d) { return 3; }

int main() {
    std::cout << bar(&foo, "test") << std::endl;
    std::cout << bar(&baz, 1.2) << std::endl;
    return 0;
}

答案 2 :(得分:1)

因为你无法直接设置参数,因此你不会吝啬。 decltype(foo)确实返回foo的实际类型,因此你可以使用它来实例化一个模板traits类,然后公开返回类型和参数类型(以某种方式),然后用它来定义你的函数。

#include <stdio.h>
int sf(int, float, double, bool) {}
template <typename RV, typename... args>
RV func(args... as) {
  printf("%d %f %f %d\n", as...);
  return sf(as...);
}
template <typename RV, typename... args>
RV(*generateFunc(RV(*)(args...)))(args...) {
  return &func<RV, args...>;
}

int main() {
  decltype(sf) *f = generateFunc(sf);
  f(42, 1.0f, 12.0, true);
}

这会生成一个匹配sf签名的函数,然后将调用转发给它。

答案 3 :(得分:1)

首先要记住的是,你需要将参数命名为no,你不能。

foo的类型是:

int(int)

所以任何虚构的声明语法如:

decltype(foo) bar { //imaginary syntax
  // can't access parameter
  return 1;
}

会遇到bar无法访问参数的问题。

所以你能做的最好就是@dyp建议的。

您可以做的另一件事是检查两个函数是否具有相同的签名:

static_assert(std::is_same<decltype(foo), decltype(bar)>::value, "Invalid bar signature");