Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SFINAE: Detecting if a function is called by a compile time known value

I like to do some check when one of my ctors are called with compile time known value. Is there a way to detect it?

So when someone call this:

A a (10);

since 10 is a compile time known constant, i like to call a special ctor, like this:

template<int Value, typename = std::enable_if_t<Value <= 100>>
A (int Value) {}

Any idea how can i solve this issue? Thanks!

like image 691
Melkon Avatar asked Dec 15 '16 15:12

Melkon


People also ask

How do you check if a function has been called?

We set it to True when the function is called. When you start your program, you will want to initialize that attribute to False, which we do above. Then we use a for loop to loop twice. The first time through it will check if the function has been called. Since it hasn't, you will see it fall to the else statement.

What is SFINAE used for in C++?

Before explaining what is SFINAE, let's explore one of its main usage: introspection. As you might be aware, C++ doesn't excel when it comes to examine the type or properties of an object at runtime. The best ability provided by default would be RTTI.

What are SFINAE errors?

Only the failures in the types and expressions in the immediate context of the function type or its template parameter types or its explicit specifier (since C++20) are SFINAE errors.

Why is is_type_complete_V defined as SFINAE?

A type must be complete in order to have the sizeof operator applied to it, so we use SFINAE to define is_type_complete_v as true provided the sizeof operator can be applied.¹ I’m not sure if this is technically legal, but all the compilers I tried seemed to be okay with it. It does lead to weird effects like this:


1 Answers

Integral constant could solve your problem:

struct A {
    template<int v, std::enable_if_t<(v <= 100)>* = nullptr>
    A(std::integral_constant<int, v>) {}
};

Then, you can use it like this:

A a{std:integral_constant<int, 7>{}};

For ease of use, you could also use something similar to what boost::hana does. It define a literal operator that transform the number into an integral constant:

A a{76_c}; // the ""_c operator outputs an std::integral_constant<int, 76>

You can read more about this operator in the boost::hana documentation

like image 67
Guillaume Racicot Avatar answered Nov 03 '22 23:11

Guillaume Racicot