Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

constexpr function for identifying compile-time constants

38 views
Skip to first unread message

David Brown

unread,
Aug 24, 2018, 3:29:23 AM8/24/18
to
Recent discussions about constexpr got me thinking...

constexpr functions can be called with parameters that are compile-time
constants, in which case the result is also a compile-time constant, or
if they are called with run-time data they are run-time functions.

Is it possible to write a constexpr function that is equivalent to gcc's
__builtin_constant_p() feature? This is defined as:

_int __builtin_constant_p(exp)

returns 1 if "exp" is known to be a compile-time constant, and 0 if not
(optimisation flags may affect what the compiler knows and returns
here). The actual value of "exp" is not evaluated or used. The return
value of the builtin is itself always a compile-time constant.


Can you write something similar in C++, so that you have:

template<typename T> constexpr const bool isConstantExpression(T x);


I can't think of a way to do it myself, but maybe that's just my lack of
imagination.



Alf P. Steinbach

unread,
Aug 24, 2018, 4:04:09 AM8/24/18
to
The following doesn't help, it outputs `false` with both g++ and Visual C++:

#include <iostream>
using namespace std;

auto main()
-> int
{
cout << boolalpha;
cout << noexcept( true? 0 : throw 0 ) << endl;
}

Cheers!,

- Alf


Öö Tiib

unread,
Aug 24, 2018, 5:59:46 PM8/24/18
to
On Friday, 24 August 2018 10:29:23 UTC+3, David Brown wrote:
> Can you write something similar in C++, so that you have:
>
> template<typename T> constexpr const bool isConstantExpression(T x);
>
>
> I can't think of a way to do it myself, but maybe that's just my lack of
> imagination.

That perhaps works:

#include <iostream>
#include <type_traits>

template<typename T>
constexpr typename std::remove_reference<T>::type makeprval(T && t)
{
return t;
}

int main(int argc, char *argv[])
{
int a = 1;
const int b = 2;
constexpr int c = 3;
const int d = argc;

// b and c are compile time constants but a and d are not.
std::cout << std::boolalpha;
std::cout << "a " << noexcept(makeprval(a)) << "\n";
std::cout << "b " << noexcept(makeprval(b)) << "\n";
std::cout << "c " << noexcept(makeprval(c)) << "\n";
std::cout << "d " << noexcept(makeprval(d)) << "\n";
}

Öö Tiib

unread,
Aug 25, 2018, 3:12:19 AM8/25/18
to
That does not work because compiler does not evaluate it as
constexpr. Also constexpr casts do not exist so got to put it into
constexpr function at least.

That seems to work on gcc:

#include <iostream>

bool constexpr is42(int i) {return i == 42? true : throw 0;}

int main()
{
int a = 42;
int const b = 42;
int constexpr c = 3;
std::cout << std::boolalpha;
std::cout << "is42(a) " << noexcept(is42(a)) << "\n";
std::cout << "is42(b) " << noexcept(is42(b)) << "\n";
std::cout << "is42(c) " << noexcept(is42(c)) << "\n";
}

0 new messages