Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Compile-time error in uninstanciated function template

My understanding of function templates has always been: if they contain invalid
C++ and you don’t instanciate them, your project will compile fine.

However, the following code:

#include <cstdio>
#include <utility>

template <typename T>
void contains_compile_time_error(T&& t) {
    int j = nullptr;
}

int main() {}

Compiles with:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  • x86-64 gcc 11.2 and flag -std=c++20;
  • x64 msvc v19.31 and flag /std:c++20;

and does not with x86-64 clang 14.0.0 (with flags -std=c++{11,14,17,20}):

error: cannot initialize a variable of type 'int' with an rvalue of type 'std::nullptr_t'
    int j = nullptr;
        ^   ~~~~~~~
1 error generated.

Even more confusing to me, the following code:

#include <cstdio>
#include <utility>

namespace ns {
struct S {};

template <typename T>
void apply(T&& t) {
    //print(std::forward<T>(t));
    ns::print(std::forward<T>(t));
}

void print(S const&) { std::puts("S"); }

}  // namespace ns

int main() {}

Does not compile with:

  • x86-64 gcc 11.2 and flag -std=c++20;
  • x64 msvc v19.31 and flag /std:c++20;
  • x86-64 clang 14.0.0 and flags -std=c++{11,14,17,20};

(all of them complaining that print is not a member of 'ns') but does compile with x64 msvc v19.31 /std:c++17.

If I call unqualified print, then the code compiles with all the above compilers.

So, my questions are:

  • is my understanding of function templates wrong?
  • why do the above compilers behave differently with the code snippets I posted?

Edit 0: as per Frank’s comment, x64 msvc v19.31 /std:c++17 /permissive- fails to compile function template apply where I call the qualified ns::print.

>Solution :

My understanding of function templates has always been: if they contain invalid C++ and you don’t instanciate them, your project will compile fine.

But what does "invalid C++" mean? You can have syntactically valid C++ that is still invalid semantically, and the semantics of C++ are highly contextual.

So there’s multiple levels of "valid" that can be checked at different times during compilation, based on the available information.

There are three types of lookups involved here.

  • Qualified lookups, such as ns::print
  • Unqualified lookups not involving template parameters, which you’d get if you tried print(S{});
  • Unqualified lookups involving template parameters, such as print(std::forward<T>(t));

Lookups are deferred for the third category, but are still performed the same as non-template functions for the other two.

Note that the code still needs to be syntactically valid, even in the case of deferred lookups, hence why typename needs to be added when doing a dependent lookup of a type.

why do the above compilers behave differently with the code snippets I posted?

As far as int j = nullptr is concerned: The program is technically ill-formed, but the diagnostics is optional. I believe this is because it’s not possible to guarantee that every single ill-formed statement can be caught in non-instantiated templates. So the code is broken, but GCC is not breaking compliance by letting it through.

For example, if S only had private constructors, then print(std::forward<T>(t)) would be flaggable as being broken since there is no possibly T that would make it valid. However, requiring compilers to be smart enough to determine this in all cases would be kind of mean.

And as for MSVC allowing ns::print: That compiler is not compliant by default on this (and other) aspect of the standard. You need to use the /permissive- compiler flag to enforce compliance.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading