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

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

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:

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

template <int val>
struct bla
{

};

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

What is the key difference between those two cases?

>Solution :

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.

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