<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/130242>130242</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Function template with concept is instanciated even if the constraint are not met
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          WorldRobertProject
      </td>
    </tr>
</table>

<pre>
    The following code is OK in MSVC, but not in clang.

    #include <iostream>
    #include <optional>

    template <typename T>
    concept HasVoid = std::is_void_v<typename T::Type>;

 template <typename T>
    concept HasNonVoid = !std::is_void_v<typename T::Type>;

    struct Void
    {
        using Type = void;
    };

 struct NonVoid
    {
        using Type = int;
    };

    template <typename T, std::enable_if_t<HasVoid<T>, int> = 0>
    void UseEnableIf(bool value)
    {
        std::cout << "Void" << std::endl;
 }

    template <typename T, std::enable_if_t<HasNonVoid<T>, int> = 0>
 void UseEnableIf(const std::optional<typename T::Type>& value)
    {
 std::cout << "NonVoid" << std::endl;
    }

    template <HasVoid T>
    void UseConcept(bool value)
    {
        std::cout << "Void" << std::endl;
    }

    template <HasNonVoid T>
    void UseConcept(const std::optional<typename T::Type>& value)
    {
        std::cout << "NonVoid" << std::endl;
    }

    int main()
    {
 UseEnableIf<Void>(true);  // OK
        UseEnableIf<NonVoid>(1);
 UseConcept<Void>(true);   // clang: error, MSVC: OK
 UseConcept<NonVoid>(1);
    }

In clang, UseConcept<Void>(true); causes errors like std::optional<void> is illegal.
It seems both the first and the second UseConcept functions are instanciated, even if the second functions's constraint is not met.
On the other hand, it works in MSVC.

I don't think the concept is a perfect replacement for std::enable_if_t,
but which behavior is correct according to the C++ standard?

clang version: 18.1.8 (Red Hat, Inc. 18.1.8-3.el9)
C++ standard: C++20

</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0VtFy6jYQ_RrxshPGSBDIgx_ACXMzd9p0btPbx4wsr7EaITHSGiZ_35FsB9JA0t62vACW95yzR8dayxD0xiLmbLZis9uRbKlxPv_deVN9cyV6-sW7P1DRqHTVS_7YINTOGHfQdgPKVQg6wMNX0BZ--vV7wXgBZUtgHcVLyki7GbNsybIlAADjQltl2gqBiUK7QB7llom7s-tuR9pZabr1_hbC7c5ISjfQyw6t3CI8HiGUswp3BF9k-O50BUzcQqCKiSUTSx2e9k5XT_u_FMe1x5cdRhix6sn-AdPPzr6SMT75MT4ACORbRRCxBkfmq_5X_LQh2h4rE1XE7uq7W2-PYD1SL-zvgGlLF7Auu86Lo7doZWnwSddPxETR289EkRzjRYd_l6iyo4mxBfgt4F2qvq8ZX5TOGdhL0yLjN2eVv3Iq11KUxEQBjPPEyPlw5URaZfreYmP_qqvB0Q8bO9OVcjbQEfeY7YvB4NcXXLjU_iDtYwf63T1rwvDQPL7foKJL-_-9P5-oGx60DwX-h1Z_0tCPOa4twVZqy_jiHeFpaETRJe2O8QX5Tp1YxVNyzfgaHr6eKHxb9xrSWDrp6nr0waZL4AN6OrqZWAJ673zMeTrfxbLnfQN1ie-08_t-HESoz3Uo2QYMHXkAo5_x7IZ2J-BdHELaGNxIE6fNPUFA3AYoHTVAcWZpHwikrdK_gMrZ09BA3VoVQQNIj6BtIGmVloRVlIt7tKDr09rXAsbnAVLivIwbq0MaflukqOTBpiJHDXpopE1wmuDg_HMYhmY_IO-hcpbxOQE12j6nwmHG6AASduhrVAQed0Yq3KIlqJ0_f1jxgmXLOIoPjVYNlNjIvXY-IinnfcSRSjlfxSFALrEVjK8YX0HsvpK-YmLdSUsbB3v0QTsbMzBZjCfjBTC--IYVfJGRD-6tGvcrV2KM5qZL93vU5cDEM5YtR1UuqhtxI0eYT-bTieBiwq9HTc7rUl7PajHnSopa1NNKzPhMZGJRyuupECOd84zPMpHNs-mMZ9fjEieiLMsZClnz6aRm0wy3UpuxMfvt2PnNSIfQYj4RGZ_ykZElmpBefTi3eIC0yjiPb0I-j0VXZbsJbJoZHSgcYUiTwXzdh-B4Sh00NaebdpqkNzE6SUxMXB-ZUetN3hDtQtzQ9CBuNDVtOVZuy_g68vdfV7vuvYzxdVIdGF_3be1z_mcAAAD__-sl8EQ">