4

I wonder if, for example, evaluated compiled on a little endian platform will return true on a big endian target platform.

constexpr bool is_little_endian()
{
    int num = 1;
    return (1 == *(char *)&num);
}

In other words, are constexpr evaluated as if on the target?

EDIT: This example isn't correct, but the question is still active.

FlashMcQueen
  • 635
  • 3
  • 13
  • 2
    Possible duplicate of [When does a constexpr function get evaluated at compile time?](https://stackoverflow.com/questions/14248235/when-does-a-constexpr-function-get-evaluated-at-compile-time) – meowgoesthedog Nov 27 '18 at 15:33
  • 1
    @meowgoesthedog That is not a duplicate question. This question is asking if the compiler will use the target platform's architecture when cross-compiling. – François Andrieux Nov 27 '18 at 15:34
  • 3
    That code shouldn't compile, since it involves the equivalent of a `reinterpret_cast` in the middle of a `constexpr` function. – Nicol Bolas Nov 27 '18 at 15:35
  • 2
    This function contains a `reinterpret_cast` expression which is not allowed in a constexpr evaluation… – Michael Kenzel Nov 27 '18 at 15:35
  • It will use the target platform. All the compilers set up their AST based on the target platform (whether same or different than host platform), so the computation is done on the target platform, obviously. It may not be a constexpr if not possible, of course. – Matthieu Brucher Nov 27 '18 at 15:35
  • @meowgoesthedog I ask in case constexpr can be evaluated at compile time, is it as if on the target? – FlashMcQueen Nov 27 '18 at 15:36
  • Adding to the answer below: It's impossible to determine endianness at comple-time without compiler magic. – HolyBlackCat Nov 27 '18 at 15:38
  • Perhaps a better way of looking at this question is asking whether `sizeof(void*)` or some other platform-specific value depends on the build system's platform or the target system's platform. – François Andrieux Nov 27 '18 at 15:40
  • For instance, for clang AST, the triple (so endianness is there as well) is known and thus the code can be properly expressed on the target platform. And I assume that this is well tested with all the corss compilers taht exist and the extent of clang optimizatiosn where lots of things are computed at compile time. – Matthieu Brucher Nov 27 '18 at 15:40
  • @FrançoisAndrieux it depends on the target platform. – Matthieu Brucher Nov 27 '18 at 15:41
  • @MatthieuBrucher Yes. I'm not asking the question, I'm proposing an alternative question that OP could use to better express what they want to know or to help other users better understand what OP is trying to find out. – François Andrieux Nov 27 '18 at 15:41
  • OK, OK sorry, I misunderstood then ;) – Matthieu Brucher Nov 27 '18 at 15:42
  • @FrançoisAndrieux I am pretty certain OP actually wants to know endiannes at compile time for practical reasons :) – SergeyA Nov 27 '18 at 15:46
  • @SergeyA Maybe. But the question title "Are constexpr evaluated on target platform?" leads me to believe it might just be an example. – François Andrieux Nov 27 '18 at 15:48
  • 2
    FWIW, C++20 offers [`std::endian`](https://en.cppreference.com/w/cpp/types/endian) – NathanOliver Nov 27 '18 at 15:54

3 Answers3

4

First off: If you compile code for a given target, then the compiler will generate code for that target. This, of course, includes expressions that are evaluated at compile-time - otherwise every cross compilation that involved such expressions would be broken.

However, just marking a function as constexpr does not guarantee that it is evaluated at compile-time. In particular, your sample function cannot (according to the standard) be evaluated at compile-time, so it is orthogonal to the primary question.

As remarked in the comments, you can't really find out endianness at compile-time without querying the compiler directly. The compiler has to know (because it has to generate code) and any reasonable compiler will provide a way for you to query this information (at compile-time).

Max Langhof
  • 23,383
  • 5
  • 39
  • 72
4

This is not a valid constexpr function as it has reinterpret_cast baked into it. This makes the whole question moot.

And the reason why this is not valid constexpr function is outlined here: https://en.cppreference.com/w/cpp/language/constexpr. In particular, constexpr function should satisfy, among others, following criteria:

...there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression

reinterpret_cast can never be a part of core constant expression.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • It's actually a good question, but its would-be "mootness" is where you've hit upon the answer - it's not possible (AFAIK) to observe the endianness difference because a sufficiently complex expression cannot be evaluated at compile-time. And (if true) that's a useful thing to know. – Lightness Races in Orbit Nov 27 '18 at 15:37
  • @LightnessRacesinOrbit yes, I do agree. – SergeyA Nov 27 '18 at 15:38
  • 2
    @MichaelKenzel, no, it is not - because a function can only be marked constexpr if `there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression` – SergeyA Nov 27 '18 at 15:39
  • I don't get it, when I check on godbolt: https://godbolt.org/z/AzWLph the output shows that there is no runtime evaluation and the output is precalculated. – FlashMcQueen Nov 27 '18 at 15:41
  • @SergeyA you're right, sorry, I got confused there for a second… – Michael Kenzel Nov 27 '18 at 15:41
  • @FlashMcQueen that must be a bug in gcc. This function should not compile because it is not a valid constexpr function. If you try clang, for example, you will see that the compiler rejects it for the reasons explained above… – Michael Kenzel Nov 27 '18 at 15:43
  • @FlashMcQueen clang doesn't want it. – Matthieu Brucher Nov 27 '18 at 15:43
  • 2
    @MichaelKenzel The standard states that no diagnostic is required in this case so it is legal for the code to compile. – NathanOliver Nov 27 '18 at 15:45
  • It's not a bug in GCC, it's the optimizer that optimizes x86 code on x86 platform. Try on another architecture (e.g. MIPS) and [see what happens](https://godbolt.org/z/YdPIDB). – rustyx Nov 27 '18 at 15:45
  • @rustyx your example uses C++11, which restricts constexpr functions undully. Try C++14. – SergeyA Nov 27 '18 at 15:46
  • @NathanOliver ah, true, I overlooked that point. So it may compile, but the program is still ill-formed… – Michael Kenzel Nov 27 '18 at 15:48
  • 1
    @rustyx with update, your point is not very clear. We see what happens - it get's compiled :) – SergeyA Nov 27 '18 at 15:50
  • @SergeyA - when cross-compiling for MIPS (big-endian) it evaluates to 0. So at least the optimizer appears to work on the target platform. – rustyx Nov 27 '18 at 15:52
2

Yes they are. If you have a C++20 compiler available (probably -std=c++2a) you can try to compile this for platforms with different endianess and see that it behaves correctly.

#include <bit>
#include <iostream>

constexpr bool are_all_scalar_types_little_endian() {
  return std::endian::native == std::endian::little;
}

constexpr bool are_all_scalar_types_big_endian() {
  return std::endian::native == std::endian::big;
}

int main() {
  std::cout << std::boolalpha
    << "little: " << are_all_scalar_types_little_endian() << '\n'
    << "big   : " << are_all_scalar_types_big_endian() << '\n'
    << "mixed : " << 
        (are_all_scalar_types_little_endian()==are_all_scalar_types_big_endian()) << '\n';
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108