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.
    – Baum mit Augen
    Commented Jul 24, 2018 at 15:26
  • 2
    Works as expected Here (C++17).
    – Jarod42
    Commented Jul 24, 2018 at 15:27
  • 2
    Got error in C++14 Demo
    – Jarod42
    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.
    – Eljay
    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.

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.