Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用decltype()声明函数签名_C++_C++11_Definition_Decltype - Fatal编程技术网

C++ 用decltype()声明函数签名

C++ 用decltype()声明函数签名,c++,c++11,definition,decltype,C++,C++11,Definition,Decltype,是否可以声明一个函数bar与函数foo具有相同的签名 int foo(int a) { return 0; } decltype(foo) bar { return 1; } //imaginary syntax 在你摆姿势的时候不是很简单,因为你不能直接设置参数。decltype(foo)确实返回foo的实际类型,因此您可以使用它来实例化模板traits类,然后以某种方式公开返回类型和参数类型,然后使用它来定义您的函数 #include <stdio.h> i

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

int foo(int a)
{
    return 0; 
}

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

在你摆姿势的时候不是很简单,因为你不能直接设置参数。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);
}
#包括
int-sf(int,float,double,bool){}
模板
RV func(参数…作为){
printf(“%d%f%f%d\n”),如;
返回sf(as…);
}
模板
RV(*生成函数(RV(*)(args…))(args…){
return&func;
}
int main(){
decltype(sf)*f=generateFunc(sf);
f(42,1.0f,12.0,真);
}

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

我认为这同样适用于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(
参数声明子句
cv限定符seqopt ref限定符opt异常规范opt属性说明符seqopt尾部返回类型opt

如8.3.5所述


首先想到的是,您需要命名参数,所以不,您不能

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");
static_断言(std::is_same::value,“无效的条形签名”);

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

#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;
}
#包括
int foo(char const*blah){return 0;}
模板
自动栏(Args…Args)->decltype(foo(Args…)
{
返回1;
}
int main(){

std::cout-Side备注:不允许使用typedefs/别名,如使用foo\u t=int(int);
要定义一个函数,声明是可以的。我认为这对于定义是不可能的。如果是:您将如何指定参数的名称?@Agentlien我不知道,所以我在这里ask@Agentlien有些情况下,您根本不需要参数名。@DanielFrey这是真的。我认为这应该是一个comment@Paranaix我正在努力在发布代码之前,请先在编译器中对代码进行检查。很抱歉重复检查。另请参阅[dcl.fct]/10我以为他说的是在
bar
中复制
foo
的函数参数,@0x499602D2我不接受这个答案;)好吧,你可以使用
decltype
复制签名,包括
bar
foo
的函数参数,但只用于声明。如果你想定义de>bar与
foo
相同的签名,您将需要使用模板。SoapBox显示了一个简单的版本;它也可以作为类模板的静态成员函数来完成,具有签名的完美复制。它具有类似的签名,但不相同;)例如,它也(贪婪地)接受其参数的隐式转换,产生不同的实例化。@dyp为true,但可能与询问者所寻找的最接近。啊,我误读了OP。我以为问题是“是否可以使用decltype声明…”。还要注意,这无法复制引用参数。如果使用完美转发,则无法正确复制按值参数。
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;
}