是否可以声明函数bar
与函数foo
具有相同的签名?
int foo(int a)
{
return 0;
}
decltype(foo) bar
{
return 1;
} //imaginary syntax
答案 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");