Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function pointers as template arguments

In the following C++ code, the line bar<func_ptr>(); //does not work causes a compilation error:

#include <iostream>

using namespace std;

void foo(){
    cout<<"Hello world";
};

template<void(*func)()> 
void bar(){
    (*func)();
}

int main() {
    using fun_ptr_type= void(*)();
    constexpr fun_ptr_type func_ptr=&foo;

    bar<&foo>();     //works
    bar<func_ptr>(); //does not work
    return 0;
}

The output of g++ is this:

src/main.cpp: In function ‘int main()’:
src/main.cpp:19:16: error: no matching function for call to ‘bar()’
  bar<func_ptr>(); //does not work
                ^
src/main.cpp:10:6: note: candidate: template<void (* func)()> void bar()
 void bar(){
      ^~~
src/main.cpp:10:6: note:   template argument deduction/substitution failed:
src/main.cpp:19:16: error: ‘(fun_ptr_type)func_ptr’ is not a valid template argument for ty
pe ‘void (*)()’
  bar<func_ptr>(); //does not work
                ^
src/main.cpp:19:16: error: it must be the address of a function with external linkage

I do not understand why it works when I directly pass the address of foo as a template argument but when I pass the constexpr func_ptr, the code does not compile anymore even though it holds exactly that address of foo at compilation time. Can someone explain this to me?

EDIT: My g++ version is

$ g++ --version
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
like image 832
phinz Avatar asked Jul 24 '18 15:07

phinz


People also ask

What is a template argument?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

Can there be more than one arguments to templates?

C++ Class Templates With Multiple ParametersIt is possible to provide more than one type when generating templates. A class template can have many generic data types.

What is the difference between the function template and template function?

"A function template is a template that is used to generate functions. A template function is a function that is produced by a template. For example, swap(T&, T&) is a function tem-plate, but the call swap(m, n) generates the actual template function that is invoked by the call."


1 Answers

From https://en.cppreference.com/w/cpp/language/template_parameters it says:

For pointers to functions, the valid arguments are pointers to functions with linkage (or constant expressions that evaluate to null pointer values). (until C++17).

Since constexpr fun_ptr_type func_ptr=&foo does not evaluate to a nullptr value at compile time, it fails if you run it with -std=c++14 or -std=c++11.

However C++17 imposes no such requirement on function pointer non type template parameters. It says:

The template argument that can be used with a non-type template parameter can be any converted constant expression of the type of the template parameter. (since C++17)

(There are some exceptions to the above but none apply to function pointers).

So the code you provide runs perfectly with the -std=c++17 option.

like image 103
Raees Rajwani Avatar answered Oct 10 '22 16:10

Raees Rajwani