4

For libraries with many large and complex template instantiations, it seems to me that one of the major considerations in deciding whether to use concepts would be whether or not the build output is smaller in size.

With SFINAE, my understanding is that the following code will cause the template instantiations std::is_function<bar> and std::enable_if<true, bool> to be included in the build output, increasing its size (albeit marginally for this example):

#include <type_traits>

template<typename F,
         typename = std::enable_if_t<
                    std::is_function<F>::value,
         bool> = true>
void foo(F& f)
{
    // do some stuff with f
}

void g();

int main()
{
    foo(g);
    return 0;
}

If a C++20 concept based on std::is_function is used instead, obviously the template will have to be instantiated to check it. But is that instantiation then written to the final build output? And does this differ depending on compiler implementation?

#include <type_traits>

template<typename F>
concept Function = std::is_function<F>::value;

template<Function F>
void foo(F& f)
{
    // do some stuff with f
}
//...
cigien
  • 57,834
  • 11
  • 73
  • 112
mousebyte
  • 61
  • 7
  • 2
    It seems like you could easily compile this code on the platform(s) you care about and find the answer quite quickly. Is there a reason you can't do that? I don't think this can be a language lawyer question or provide answers for all compilers, because it seems like a quality-of-implementation issue, not a standards issue. – John Zwinck Jan 27 '21 at 21:48

1 Answers1

5

It seems you are worried about code size.

Classes, and here I include instantiations of class templates, are just abstract pieces of information that the compiler knows about. They do not contribute to the code size.

Only functions, including member functions, contribute to code size. Member functions of class templates contribute to code size only when they are instantiated because the way in which they are used requires it (the C++ standard calls it "ODR-used").

In your examples, no member functions of std::is_function and std::enable_if are ODR-used, so they are not instantiated, and they do not contribute to code size.

But is that instantiation then written to the final build output?

No code is generated. But typically compilers write debugging information to the output. In that sense, something is written to the output.

And does this differ depending on compiler implementation?

As far as debugging information is concerned: yes. But whether an instantiation occurs is governed by the rules of the language, and there should not be a difference between compilers.

j6t
  • 9,150
  • 1
  • 15
  • 35
  • Huh, I never quite understood what "ODR-used" meant. The idea of pure abstract bases and 'mix-ins' just clicked with me in a whole new way. When you say only functions contribute to code size, does that also apply to non-templated classes? If so I think I definitely need to look further under the hood, if only for curiosity's sake. – mousebyte Jan 28 '21 at 06:48
  • 1
    @mousebyte Yes, it's the same with non-templated classes. – j6t Jan 28 '21 at 07:27