c++ - 通过函数传递模板参数时出错

标签 c++ templates typetraits

我写了一些实用程序来描述函数的返回类型,如代码所示。为什么将函数传递给 traits 函数后 traits 不能工作? 感谢您的大力帮助。

template <class> 
struct FunctionHelper;

template <class R, class... ArgsT> 
struct FunctionHelper<R(ArgsT...)> {
  typedef R type;
};

template <class R, class... ArgsT> 
struct FunctionHelper<R *(ArgsT...)> {
  typedef R type;
};

int sum(int a, int b);
int *sum1(int a, int b);

template <class Func> 
void traits(Func func) {
  typename FunctionHelper<Func>::type value;
}

int main() {
  traits(sum);     // Here is error. error C2027: use of undefined type
  traits<decltype(sum)>(sum);  // Here works fine
  FunctionHelper<decltype(sum)>::type value; // Here works fine
}

MSVS 14.1 中的错误信息如下所示

[build] E:\source\cpp\function_traits\main.cpp(17,34): error C2027: use of undefined type 'FunctionHelper<Func>' [E:\source\cpp\function_traits\build\func_traits.vcxproj]
[build]           with
[build]           [
[build]               Func=int (__cdecl *)(int,int)
[build]           ]
[build] E:\source\cpp\function_traits\main.cpp(17): message : see declaration of 'FunctionHelper<Func>' [E:\source\cpp\function_traits\build\func_traits.vcxproj]
[build]           with
[build]           [
[build]               Func=int (__cdecl *)(int,int)
[build]           ]
[build] E:\source\cpp\function_traits\main.cpp(21): message : see reference to function template instantiation 'void traits<int(__cdecl *)(int,int)>(Func)' being compiled [E:\source\cpp\function_traits\build\func_traits.vcxproj]
[build]           with
[build]           [
[build]               Func=int (__cdecl *)(int,int)
[build]           ]
[build] E:\source\cpp\function_traits\main.cpp(17,1): error C2065: 'type': undeclared identifier [E:\source\cpp\function_traits\build\func_traits.vcxproj]
[build] E:\source\cpp\function_traits\main.cpp(17,39): error C2146: syntax error: missing ';' before identifier 'value' [E:\source\cpp\function_traits\build\func_traits.vcxproj]
[build] E:\source\cpp\function_traits\main.cpp(17,39): error C2065: 'value': undeclared identifier [E:\source\cpp\function_traits\build\func_traits.vcxproj]

最佳答案

如评论中所述,

template <class R, class... ArgsT> 
struct FunctionHelper<R *(ArgsT...)> {
  typedef R type;
};

特化 FunctionHelper 用于返回指针的函数,而不是用于 函数指针。

至于

traits(sum);     // Here is error. error C2027: use of undefined type

我建议你看看Template argument deduction .

因为你的参数 func 不是引用类型,这里:

template <class Func> 
void traits(Func func) {
  typename FunctionHelper<Func>::type value;
}

以下规则适用:

Before deduction begins, the following adjustments to P and A are made:

  1. If P is not a reference type,

    a. [...]

    b. otherwise, if A is a function type, A is replaced by the pointer type obtained from function-to-pointer conversion;

template<class T>
void f(T);
 
// ...
 
void b(int);
f(b); // P = T, A = void(int), adjusted to void(*)(int): deduced T = void(*)(int)

因此,您的 Func 类型被推断为 int(*)(int,int) 并且编译失败,因为没有 FunctionHelper 的特化用于函数指针。

您可以通过将 traits 更改为

来获得您期望的行为
template <class Func>
void traits(Func const& func) {
    typename FunctionHelper<Func>::type value;
}

关于c++ - 通过函数传递模板参数时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71937633/

相关文章:

python - 如何使用 Jinja2 模板制作一个简单的计数器?

c++ - 无法将 std::function move 到 map 中

c++ - 当我调用 strcmp 从 'int' 到 'const char*' 的无效转换时出错

c++ - 编译带有 "gcc -c"的 C++ 程序顺利通过。为什么?

c++ - 类中已删除的析构函数显示为虚拟/直接基类或一种非静态数据成员

c++ - 构造函数 SFINAE 和继承在 clang 中失败

c++ - 返回默认构造值的模板函数

c++ - 检测结构是否有填充

c++ - 支持 g++ 中的类型属性

c++ - Eric Niebler 的 std::is_function 实现如何工作?