Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When are constexpr function templates instantiated?

I'm working on a proposal to make the functional header functions constexpr. (std::invoke, std::reference_wrapper, std::bind, std::mem_fn, std::not_fn)

  • Preview of the proposal

I've learned that adding constexpr can break existing code because constexpr functions are eagerly instantiated.

template<class T>
int f(T){
    return T::not_existing_member;
}

template<class T>
constexpr int g(T){
    return T::not_existing_member;
}

int main(){
    decltype(f(0)) a; // Well-formed
    decltype(g(0)) b; // Ill-formed if the function body is instantiated
}

GCC compiles this code, clang doesn't. I describe in my proposal how you can handle the eager instantiation with overloads using the example of std::bind.

Can you tell me where in the standard it is described when a compiler has to and when it is allowed to instantiate a function template?

More precisely I want to know if in the following example the identical behavior of GCC and clang is enforced by the standard or is implementation defined:

template<class T>
struct Foo{
    constexpr int f(){
        return 0;
    }

    constexpr int f()const{
        return T::not_existing_member;
    }
};

int main(){
    /* constexpr */ Foo<int> foo;
    foo.f(); // Ill-formed with, Well-formed without constexpr by the standard?
}

Both GCC and clang compile the code if foo is not constexpr and both reject it if it is.

like image 313
Benjamin Buch Avatar asked Oct 07 '16 12:10

Benjamin Buch


1 Answers

Example #1 is active CWG issue 1581. It is currently not completely specified what the correct behavior should be. The direction seems to be that constexpr instantiation should be eager, but this needs to be clarified at some point in the future.

Example #2 is straightforward: invoking int Foo<int>::f() const is ill-formed. That happens when your foo object is const but not when it's non-const. Member functions of class templates are only instantiated when used, and if your Foo<int> object is non-const, we never instantiate the const member function, so the code is well-formed. constexpr isn't relevant here.

like image 118
Barry Avatar answered Oct 28 '22 10:10

Barry