2

I encountered a problem when using constexpr functions together with lambdas. The following code is a minimal version which reproduces the error:

#include <iostream>

constexpr unsigned bar(unsigned q) {
    return q;
}

template<unsigned N>
unsigned foo() {
    return N;
}

template<typename F>
void print(F f) {
    std::cout << f() << std::endl;
}

template<unsigned Q>
int stuff() {
    constexpr unsigned n = bar(Q);
    print([]() { return foo<n>(); });
}

int main() {
    stuff<13>();
}

When compiling with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) there are the following compiler errors:

constexpr_template.cpp: In lambda function:
constexpr_template.cpp:24:9:   instantiated from ‘stuff() [with unsigned int Q = 13u]::<lambda()>’
constexpr_template.cpp:24:2:   instantiated from ‘int stuff() [with unsigned int Q = 13u]’
constexpr_template.cpp:29:12:   instantiated from here
constexpr_template.cpp:24:32: error: no matching function for call to ‘foo()’
constexpr_template.cpp:24:32: note: candidate is:
constexpr_template.cpp:9:10: note: template<unsigned int N> unsigned int foo()

Now the strange part is, if constexpr unsigned n = bar(Q); is changed into constexpr unsigned n = Q; it works. What is also working is print([]() { return foo<bar(Q)>(); });...

Is this a bug in GCC or what am I doing wrong?

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
Danvil
  • 22,240
  • 19
  • 65
  • 88

1 Answers1

0

Gcc 4.6 was the first version to support constexpr, and it is not unusual for minor bugs to be present upon release of such features. You can verify from this Live Example on Coliru that gcc 4.8.1 and Clang 3.4 SVN correctly parse your code. You probably should upgrade your compiler accordingly.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • @Danvil what did you expect from using a pre-C++11 Standard compiler? curent gcc 4.8 behaves similarly wrt C++14, so in three years that version is also ancient ;-) My rule of thumb: gcc 4.6 = alpha, 4.7 = beta, 4.8 = rtm – TemplateRex Aug 16 '13 at 19:55