Home > front end >  Error on pass template argument through function
Error on pass template argument through function

Time:04-23

I write some utility to traits the return type of a function As the code shown. why the traits can't work after pass the function into traits function? Thanks for your great help.

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
}

The error message in MSVS 14.1 shows below

[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]

CodePudding user response:

As noted in the comments,

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

specializes FunctionHelper for a function returning a pointer, not for a function pointer.

As for

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

I suggest you have a look at Template argument deduction.

Since your parameter func is not a reference type, here:

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

The following rule applies:

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)

So, your Func type is deduced as int(*)(int,int) and compilation fails because there's no specialization of FunctionHelper for a function pointer.

You may get you behavior you expect by changing traits to

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