12

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. 
6
  • 2
    No repro with gcc8 and clang6. Commented Jul 24, 2018 at 15:26
  • 2
    Works as expected Here (C++17). Commented Jul 24, 2018 at 15:27
  • 2
    Got error in C++14 Demo Commented Jul 24, 2018 at 15:29
  • I remember some change with regardes to pointers to globals vs constexpr literals as being valid for template parameters since C++11. But I don't remember if this is one of those cases, nor how to find it. Commented Jul 24, 2018 at 15:32
  • Same experience as Jarod42. C++17 it works; C++14 spits out an error. Commented Jul 24, 2018 at 15:33

1 Answer 1

11

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.