Why does a Template inside a consteval function accepts a function parameter as one of its template parameters?
Asked Answered
S

1

5

I tried to extract a minimal working example from my codebase:

#include <concepts>

enum class unit_type
{
};

template <typename Candidate>
concept unit_c = requires()
{
    requires std::semiregular<Candidate>;
    { Candidate::type } -> std::same_as<const unit_type&>;
};

struct unit
{
    static constexpr unit_type type{};
};

template<unit_c auto unit_1, unit_c auto unit_2>
struct unit_product
{
    static constexpr unit_type type{};
};

template <unit_c Unit1, unit_c Unit2>
consteval unit_c auto operator*(Unit1 unit_1, Unit2 unit_2) noexcept
{
    return unit_product<unit_1, unit_2>{};
}

int main()
{
    constexpr unit_c auto a = unit{} * unit{};

    return 0;
}

The above code compiles fine. but why? I thought one cannot pass the parameters of a consteval function to a template. All gcc, clang and msvc all accept the above code.

This code produces an error:

template <int val>
struct bla
{

};

consteval void bla_test(int val)
{
    bla<val>;
}

What is the key difference between those two cases?

Staminody answered 29/1 at 12:11 Comment(0)
A
7

Copying a unit object (with the defaulted copy constructor) does not actually access that object (since it has no members). So, creating a copy to use as the argument for the NTTP is a constant expression even if the initial unit object isn't a constant expression.

It is a similar thing to calling a member function that doesn't access *this:

unit a;
constexpr unit b = a;  // a isn't accessed

std::array<int, 5> arr;
constexpr std::size_t sz = arr.size();  // arr isn't accessed

The key difference with the int case is that the value of int val would be accessed if you tried to copy it.

Argyrol answered 29/1 at 12:29 Comment(1)
While this should work in theory, in practice it's a different story. As GCC is notoriously bad with handling constructs that rely on this capability. See also this and this post.Urbana

© 2022 - 2024 — McMap. All rights reserved.