Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #70935 > unrolled thread

Is there a way to determine endianess in a constexpr-function ?

Started byBonita Montero <Bonita.Montero@gmail.com>
First post2020-01-01 17:46 +0100
Last post2020-01-05 08:38 +0100
Articles 16 — 8 participants

Back to article view | Back to comp.lang.c++


Contents

  Is there a way to determine endianess in a constexpr-function ? Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-01 17:46 +0100
    Re: Is there a way to determine endianess in a constexpr-function ? Bo Persson <bo@bo-persson.se> - 2020-01-01 18:49 +0100
      Re: Is there a way to determine endianess in a constexpr-function ? Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-01 18:54 +0100
        Re: Is there a way to determine endianess in a constexpr-function ? David Brown <david.brown@hesbynett.no> - 2020-01-01 23:21 +0100
          Re: Is there a way to determine endianess in a constexpr-function ? Robert Wessel <robertwessel2@yahoo.com> - 2020-01-01 18:26 -0600
          Re: Is there a way to determine endianess in a constexpr-function ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-02 00:47 +0000
    Re: Is there a way to determine endianess in a constexpr-function ? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2020-01-02 22:28 -0500
      Re: Is there a way to determine endianess in a constexpr-function ? Siri Cruise <chine.bleu@yahoo.com> - 2020-01-02 19:51 -0800
      Re: Is there a way to determine endianess in a constexpr-function ? Öö Tiib <ootiib@hot.ee> - 2020-01-02 23:14 -0800
      Re: Is there a way to determine endianess in a constexpr-function ? Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-03 08:31 +0100
        Re: Is there a way to determine endianess in a constexpr-function ? Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-03 08:43 +0100
          Re: Is there a way to determine endianess in a constexpr-function ? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2020-01-05 00:51 -0500
            Re: Is there a way to determine endianess in a constexpr-function ? Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-05 07:43 +0100
              Re: Is there a way to determine endianess in a constexpr-function ? Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-05 08:31 +0100
                Re: Is there a way to determine endianess in a constexpr-function ? Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-05 08:34 +0100
                Re: Is there a way to determine endianess in a constexpr-function ? Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-05 08:38 +0100

#70935 — Is there a way to determine endianess in a constexpr-function ?

FromBonita Montero <Bonita.Montero@gmail.com>
Date2020-01-01 17:46 +0100
SubjectIs there a way to determine endianess in a constexpr-function ?
Message-ID<quiidc$qa1$1@news.albasani.net>
Is there a way to determine endianess in a constexpr-function
which might return true for little endian and false for big
endian? I guess not, but maybe I din't consider a trick here.

[toc] | [next] | [standalone]


#70940

FromBo Persson <bo@bo-persson.se>
Date2020-01-01 18:49 +0100
Message-ID<h744cjF4glqU1@mid.individual.net>
In reply to#70935
On 2020-01-01 at 17:46, Bonita Montero wrote:
> Is there a way to determine endianess in a constexpr-function
> which might return true for little endian and false for big
> endian? I guess not, but maybe I din't consider a trick here.

"Not" is probably the correct answer here, so in C++20 we get 
std::endian where the implementation provides the info.

https://en.cppreference.com/w/cpp/types/endian


     Bo Persson

[toc] | [prev] | [next] | [standalone]


#70941

FromBonita Montero <Bonita.Montero@gmail.com>
Date2020-01-01 18:54 +0100
Message-ID<quimd9$hek$2@news.albasani.net>
In reply to#70940
>> Is there a way to determine endianess in a constexpr-function
>> which might return true for little endian and false for big
>> endian? I guess not, but maybe I din't consider a trick here.

> "Not" is probably the correct answer here, so in C++20 we get 
> std::endian where the implementation provides the info.
> https://en.cppreference.com/w/cpp/types/endian

Where's the support for the DEC PDP-11 and Honeywell 316 endianess???
;-)

[toc] | [prev] | [next] | [standalone]


#70947

FromDavid Brown <david.brown@hesbynett.no>
Date2020-01-01 23:21 +0100
Message-ID<quj613$6nk$1@dont-email.me>
In reply to#70941
On 01/01/2020 18:54, Bonita Montero wrote:
>>> Is there a way to determine endianess in a constexpr-function
>>> which might return true for little endian and false for big
>>> endian? I guess not, but maybe I din't consider a trick here.
> 
>> "Not" is probably the correct answer here, so in C++20 we get 
>> std::endian where the implementation provides the info.
>> https://en.cppreference.com/w/cpp/types/endian
> 
> Where's the support for the DEC PDP-11 and Honeywell 316 endianess???
> ;-)
> 

Gone - along with ones' complement integers.

If your code is limited to a known set of compilers or platforms, most 
have predefined macros that give you the endianness.  There are some 
header files floating around the web that have checks for a large number 
of different toolchains if you don't want to read all the documentation 
yourself.

[toc] | [prev] | [next] | [standalone]


#70948

FromRobert Wessel <robertwessel2@yahoo.com>
Date2020-01-01 18:26 -0600
Message-ID<31eq0f58f4jc0jp7k53p3tfit7tt2hmpoa@4ax.com>
In reply to#70947
On Wed, 1 Jan 2020 23:21:23 +0100, David Brown
<david.brown@hesbynett.no> wrote:

>On 01/01/2020 18:54, Bonita Montero wrote:
>>>> Is there a way to determine endianess in a constexpr-function
>>>> which might return true for little endian and false for big
>>>> endian? I guess not, but maybe I din't consider a trick here.
>> 
>>> "Not" is probably the correct answer here, so in C++20 we get 
>>> std::endian where the implementation provides the info.
>>> https://en.cppreference.com/w/cpp/types/endian
>> 
>> Where's the support for the DEC PDP-11 and Honeywell 316 endianess???
>> ;-)
>> 
>
>Gone - along with ones' complement integers.


Are byte orders other than the two major ones actually disallowed now
(or at least in C++20)?  The enum provides at least a small loophole
for non-big, non-little endian implorations.

[toc] | [prev] | [next] | [standalone]


#70949

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2020-01-02 00:47 +0000
Message-ID<87sgkyptu8.fsf@bsb.me.uk>
In reply to#70947
David Brown <david.brown@hesbynett.no> writes:

> On 01/01/2020 18:54, Bonita Montero wrote:
>>>> Is there a way to determine endianess in a constexpr-function
>>>> which might return true for little endian and false for big
>>>> endian? I guess not, but maybe I din't consider a trick here.
>>
>>> "Not" is probably the correct answer here, so in C++20 we get
>>> std::endian where the implementation provides the info.
>>> https://en.cppreference.com/w/cpp/types/endian
>>
>> Where's the support for the DEC PDP-11 and Honeywell 316 endianess???
>> ;-)
>>
>
> Gone - along with ones' complement integers.

Not entirely!  An implementation must signal a non-uniform endianness,
but it can't, using std::endian alone, say much more about it.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#70992

FromPavel <pauldontspamtolk@removeyourself.dontspam.yahoo>
Date2020-01-02 22:28 -0500
Message-ID<1yyPF.127450$QU2.87340@fx01.iad>
In reply to#70935
Bonita Montero wrote:
> Is there a way to determine endianess in a constexpr-function
> which might return true for little endian and false for big
> endian? I guess not, but maybe I din't consider a trick here.
Why not, it's actually not difficult.

Below is a simple example (actually returns true for big endian) but I think
more complex checks can be built upon same principle.

#include <cstdint>
#include <iostream>
using namespace std;

enum ProbeEnum : int16_t { ProbeValue = 0x0100 };
constexpr union {
  ProbeEnum p;
  char ca[2];
} ProbeVal{ProbeValue};

constexpr
bool
IsBigEndian()
{
  return !!ProbeVal.ca[0];
}

int
main(int, char*[])
{
  cout << "IsBigEndian=" << IsBigEndian() << endl;


  return 0;
}

HTH
-Pavel

[toc] | [prev] | [next] | [standalone]


#70993

FromSiri Cruise <chine.bleu@yahoo.com>
Date2020-01-02 19:51 -0800
Message-ID<chine.bleu-1058BC.19512102012020@reader.eternal-september.org>
In reply to#70992
In article <1yyPF.127450$QU2.87340@fx01.iad>,
 Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> wrote:

> Below is a simple example (actually returns true for big endian) but I think
> more complex checks can be built upon same principle.

Four bytes let's you detect Dec's middle endian.

-- 
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted.    @
'I desire mercy, not sacrifice.'                                    /|\
The first law of discordiamism: The more energy   This post         / \
to make order is nore energy made into entropy.   insults Islam.  Mohammed

[toc] | [prev] | [next] | [standalone]


#71000

FromÖö Tiib <ootiib@hot.ee>
Date2020-01-02 23:14 -0800
Message-ID<480ef1d4-c8fa-4d08-bc06-35f7199446a2@googlegroups.com>
In reply to#70992
On Friday, 3 January 2020 05:29:08 UTC+2, Pavel  wrote:
> Bonita Montero wrote:
> > Is there a way to determine endianess in a constexpr-function
> > which might return true for little endian and false for big
> > endian? I guess not, but maybe I din't consider a trick here.
> Why not, it's actually not difficult.
> 
> Below is a simple example (actually returns true for big endian) but I think
> more complex checks can be built upon same principle.
> 
> #include <cstdint>
> #include <iostream>
> using namespace std;
> 
> enum ProbeEnum : int16_t { ProbeValue = 0x0100 };
> constexpr union {
>   ProbeEnum p;
>   char ca[2];
> } ProbeVal{ProbeValue};
> 
> constexpr
> bool
> IsBigEndian()
> {
>   return !!ProbeVal.ca[0];
> }
> 
> int
> main(int, char*[])
> {
>   cout << "IsBigEndian=" << IsBigEndian() << endl;
> 
> 
>   return 0;
> }

In C++ type punning through union is undefined behavior. Type punning
through reinterpret cast to pointer of bytes and type punning through
memcpy are valid but are not constexpr in C++. So I feel that your code
has undefined behavior.

[toc] | [prev] | [next] | [standalone]


#71001

FromBonita Montero <Bonita.Montero@gmail.com>
Date2020-01-03 08:31 +0100
Message-ID<qumqk4$okt$1@news.albasani.net>
In reply to#70992
>> Is there a way to determine endianess in a constexpr-function
>> which might return true for little endian and false for big
>> endian? I guess not, but maybe I din't consider a trick here.
> Why not, it's actually not difficult.

> Below is a simple example (actually returns true for big endian)
> but I think more complex checks can be built upon same principle.
> #include <cstdint>
> #include <iostream>
> using namespace std;
> enum ProbeEnum : int16_t { ProbeValue = 0x0100 };
> constexpr union {
>    ProbeEnum p;
>    char ca[2];
> } ProbeVal{ProbeValue};
> constexpr
> bool
> IsBigEndian()
> {
>    return !!ProbeVal.ca[0];
> }
> int
> main(int, char*[])
> {
>    cout << "IsBigEndian=" << IsBigEndian() << endl;
> 
> 
>    return 0;
> }

IsBigEndian isn't guaranteed compile-time evaluated.

[toc] | [prev] | [next] | [standalone]


#71002

FromBonita Montero <Bonita.Montero@gmail.com>
Date2020-01-03 08:43 +0100
Message-ID<qumrb1$n08$1@news.albasani.net>
In reply to#71001
Am 03.01.2020 um 08:31 schrieb Bonita Montero:
>>> Is there a way to determine endianess in a constexpr-function
>>> which might return true for little endian and false for big
>>> endian? I guess not, but maybe I din't consider a trick here.
>> Why not, it's actually not difficult.
> 
>> Below is a simple example (actually returns true for big endian)
>> but I think more complex checks can be built upon same principle.
>> #include <cstdint>
>> #include <iostream>
>> using namespace std;
>> enum ProbeEnum : int16_t { ProbeValue = 0x0100 };
>> constexpr union {
>>    ProbeEnum p;
>>    char ca[2];
>> } ProbeVal{ProbeValue};
>> constexpr
>> bool
>> IsBigEndian()
>> {
>>    return !!ProbeVal.ca[0];
>> }
>> int
>> main(int, char*[])
>> {
>>    cout << "IsBigEndian=" << IsBigEndian() << endl;
>>
>>
>>    return 0;
>> }
> 
> IsBigEndian isn't guaranteed compile-time evaluated.

if i do: "if constexpr( IsBigEndian() )" I'll get:
"error C2131: expression did not evaluate to a constant"

[toc] | [prev] | [next] | [standalone]


#71137

FromPavel <pauldontspamtolk@removeyourself.dontspam.yahoo>
Date2020-01-05 00:51 -0500
Message-ID<0QeQF.95983$Cb2.42884@fx44.iad>
In reply to#71002
Bonita Montero wrote:
> Am 03.01.2020 um 08:31 schrieb Bonita Montero:
>>>> Is there a way to determine endianess in a constexpr-function
>>>> which might return true for little endian and false for big
>>>> endian? I guess not, but maybe I din't consider a trick here.
>>> Why not, it's actually not difficult.
>>
>>> Below is a simple example (actually returns true for big endian)
>>> but I think more complex checks can be built upon same principle.
>>> #include <cstdint>
>>> #include <iostream>
>>> using namespace std;
>>> enum ProbeEnum : int16_t { ProbeValue = 0x0100 };
>>> constexpr union {
>>>    ProbeEnum p;
>>>    char ca[2];
>>> } ProbeVal{ProbeValue};
>>> constexpr
>>> bool
>>> IsBigEndian()
>>> {
>>>    return !!ProbeVal.ca[0];
>>> }
>>> int
>>> main(int, char*[])
>>> {
>>>    cout << "IsBigEndian=" << IsBigEndian() << endl;
>>>
>>>
>>>    return 0;
>>> }
>>
>> IsBigEndian isn't guaranteed compile-time evaluated.
> 
> if i do: "if constexpr( IsBigEndian() )" I'll get:
> "error C2131: expression did not evaluate to a constant"
Right. If I try to do

  constexpr bool ibe = IsBigEndian();

I receive more explicit error message from gcc:

 error: accessing ‘Endian::ca’ member instead of initialized ‘Endian::p’ member
in constant expression

So the Big Brother is watching.. Then the answer to your question is probably
"not possible until C++20". With C++20 you should be able to write a similar
code using bit_cast which is constexpr as mentioned by Bo Persson on another thread.

[toc] | [prev] | [next] | [standalone]


#71138

FromBonita Montero <Bonita.Montero@gmail.com>
Date2020-01-05 07:43 +0100
Message-ID<qus0ir$2f2$1@news.albasani.net>
In reply to#71137
 > So the Big Brother is watching.. Then the answer to your question is
 > probably "not possible until C++20". With C++20 you should be able to
 > write a similar code using bit_cast which is constexpr as mentioned by
 > Bo Persson on another thread.

C++20 should not only provide an enum which tells if the machine is big
or little endian. It should also provide wrapper-classes of all basic
integral and floating-point datatypes in big as well as little endian
with overloaded operators that swap the bytes if appropriate on reading
and assignment. This could be f.e. done internally by the standard
library's specific intrinsics for byte-swapping (f.e. with BSWAP
for x86).

[toc] | [prev] | [next] | [standalone]


#71139

FromBonita Montero <Bonita.Montero@gmail.com>
Date2020-01-05 08:31 +0100
Message-ID<qus3c3$vlc$1@news.albasani.net>
In reply to#71138
>> So the Big Brother is watching.. Then the answer to your question is
>> probably "not possible until C++20". With C++20 you should be able to
>> write a similar code using bit_cast which is constexpr as mentioned by
>> Bo Persson on another thread.

> C++20 should not only provide an enum which tells if the machine is big
> or little endian. It should also provide wrapper-classes of all basic
> integral and floating-point datatypes in big as well as little endian
> with overloaded operators that swap the bytes if appropriate on reading
> and assignment. This could be f.e. done internally by the standard
> library's specific intrinsics for byte-swapping (f.e. with BSWAP
> for x86).

So something like this:

#if defined(_MSC_VER)
     #include <intrin.h>
#endif
#include <cstdint>

template<typename T>
struct big_endian
{
     T operator =( T value );
       operator T();
private:
     big_endian();
};

template<>
struct big_endian<std::uint32_t>
{
                   big_endian() = default;
                   big_endian( std::uint32_t value );
     std::uint32_t operator =( std::uint32_t value );
                   operator std::uint32_t();
private:
     std::uint32_t swap( std::uint32_t value );
     std::uint32_t m_value;
};

inline
big_endian<std::uint32_t>::big_endian( std::uint32_t value )
{
     m_value = swap( value );
}

inline
std::uint32_t big_endian<std::uint32_t>::operator =( std::uint32_t value )
{
     m_value = swap( value );
     return value;
}

inline
big_endian<std::uint32_t>::operator std::uint32_t()
{
     return swap( m_value );
}

inline
std::uint32_t big_endian<std::uint32_t>::swap( std::uint32_t value )
{
#if defined(_MSC_VER)
     return _byteswap_ulong( value );
#elif defined(__GNUC__)
     return __builtin_bswap32( value );
#else
     std::uint32_t swapA = (value & 0x0000FFFFu) << 16,
              swapB = (value & 0xFFFF0000u) >> 16;
     return (swapA & 0x00FF00FFu) << 8 | (swapA & 0xFF00FF00u) >> 8;
#endif
}

[toc] | [prev] | [next] | [standalone]


#71140

FromBonita Montero <Bonita.Montero@gmail.com>
Date2020-01-05 08:34 +0100
Message-ID<qus3hp$q23$1@news.albasani.net>
In reply to#71139
>      std::uint32_t swapA = (value & 0x0000FFFFu) << 16,
>               swapB = (value & 0xFFFF0000u) >> 16;
>      return (swapA & 0x00FF00FFu) << 8 | (swapA & 0xFF00FF00u) >> 8;

Forget it, doesn't work, but care about the principle.

[toc] | [prev] | [next] | [standalone]


#71141

FromBonita Montero <Bonita.Montero@gmail.com>
Date2020-01-05 08:38 +0100
Message-ID<qus3pf$qh8$1@news.albasani.net>
In reply to#71139
>      std::uint32_t swapA = (value & 0x0000FFFFu) << 16,
>               swapB = (value & 0xFFFF0000u) >> 16;
>      return (swapA & 0x00FF00FFu) << 8 | (swapA & 0xFF00FF00u) >> 8;

This is correct:
     std::uint32_t swapA = (value & 0x0000FFFFu) << 16 | (value & 
0xFFFF0000u) >> 16;
     return (swapA & 0x00FF00FFu) << 8 | (swapB & 0xFF00FF00u) >> 8;

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web