Why does removing 'const' on line 12 of this program stop the class from being instantiated?

Removing const from line 12 prevents the class What from being instantiated during compilation. I do not expect What to ever be instantiated, regardless of constness in the declaration. This is consistent between clang, gcc and MSVC so I assume it is standard. Marking the constructor explicit also does not prevent the instantiation. What am I not understanding here? Why does constness make a difference?

template <typename T> constexpr bool just_false() { return false; }

template<typename T>
class What {
    static_assert(just_false<T>(), "Why was this class instantiated?");
};

struct The {};

struct Heck {
    Heck(The) {}
    Heck(const What<int>&); // Removing 'const' from this line stops 'What<int>' from being instantiated
};

int main() {
    The the;
    Heck{the};
}

The just_false incantation is just to prevent the static assert from always triggering regardless of instantiation.

Compiler explorer link: https://godbolt.org/z/8cETcfss5

>Solution :

If const is there, and What<int> happens to have a constructor taking The, that would allow Heck(const What<int> &) to be used (because a const reference can bind to a temporary produced by such constructor). Checking for that constructor of What<int> requires instantiating What<int>.

If there is no const, no implementation of What<int> could possibly make Heck(What<int> &); be called, so there’s no point in instantiating it.


But it seems that no matter what constructor What<int> has, the Heck(The) overload would take precedence, so strictly speaking, this instantiation seems to be unnecessary in this specific case.

Leave a Reply