Topic: Testing for supported features: Per-feature macros?


Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 26 Jul 2015 10:42:57 -0700 (PDT)
Raw View
------=_Part_2_1561314666.1437932577617
Content-Type: multipart/alternative;
 boundary="----=_Part_3_96256940.1437932577617"

------=_Part_3_96256940.1437932577617
Content-Type: text/plain; charset=UTF-8

I'm part of a group that is tasked with updating a public domain
cryptographic library, Crypto++. Our current goal is to have it compile
cleanly while enabling all warnings, with all the latest as well as older
C++ compiler versions.

A common issue in libraries with similar goals is how to detect that a
particular language feature is implemented, so as to either make use of it
or not. Currently, in most cases, this requires testing macros for specific
compiler versions.

For example. Our latest issue is that some destructors in Crypto++ may
throw exceptions. We could rewrite those destructors, but that would
involve changes in behavior that would require a larger version bump,
compared to the minor version update we are tasked with.

We have determined that the destructors in question are safe to mark
noexcept(false). In the worst case, this will preserve these destructors'
intended behavior.

In order to implement this, we now have to test with all the compiler
versions that we support, and figure out in which versions (1) noexcept is
not supported, or (2) noexcept is supported AND we must use it to preserve
behavior.

We will probably end up implementing a macro defined based on a number of
#if defined(...) conditions. With some compilers, we will be able to use
the value of the __cplusplus macro to determine that noexcept is supported
and required. With other compilers - most prominently, MSVC 2015
- noexcept(false) is required to preserve behavior AND avoid a compiler
warning, BUT __cplusplus remains defined as 199711. In this case, we need
to test conditionally for the MSVC compiler version.

One might argue that MS should bump their __cplusplus macro to at least
201103. However, this would break code that depends on C++11 features that
MSVC does not implement. It is in fact sound that MSVC defines their
__cplusplus macro with the old value, as long as not *all* C++11 features
are yet supported.

This then suggests that future C++ versions could benefit from a way to
test for the presence of individual features, because at least *some*
implementations are likely to have partial support for the new language
version.

I can envision two ways to do this:

- Explicitly.

In this case, each individual new language feature should come with an
accompanying macro that an implementation can enable to indicate support
for that feature. For example, there could be lots of standard macros such
as: __noexcept_supported

- Generically.

In this case, a library author could embed sentinel code that may or may
not compile; however, a failure would not produce a warning or an error.
Instead, successful compilation of the code snippet would lead to
conditional behavior. Example:

#test
void f() noexcept {}
#if noerrors
#define MYLIBRARY_NOEXCEPT(X) noexcept(X)
#else
#define MYLIBRARY_NOEXCEPT(X)
#endif
#endtest

In the example above, #test starts a sentinel code block which has local
scope (implied anonymous namespace), which may or may not compile, and ends
with the next preprocessor directive. Then, special operators "noerrors"
and "nowarnings" are available for use in #if and #elif, and
remain available until #endtest.

I understand everyone hates macros and the preprocessor in general.
However, adapting code to multiple compilers is a problem that the language
doesn't solve in any other way.

It seems to me that sentinel compilation via preprocessor directives would
be a useful and generic way to solve this issue.


--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_3_96256940.1437932577617
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>I&#39;m part of a group that is tasked with updating =
a public domain cryptographic library, Crypto++. Our current goal is=C2=A0t=
o=C2=A0have it compile cleanly=C2=A0while enabling all warnings, with all t=
he latest as well as older C++ compiler versions.</div><div><br></div><div>=
A common issue in libraries=C2=A0with similar goals=C2=A0is how to detect t=
hat a particular language feature is implemented, so as to either make use =
of it or not. Currently, in most cases, this requires testing macros for sp=
ecific compiler versions.</div><div><br></div><div>For example.=C2=A0Our la=
test issue is that some destructors in Crypto++ may throw exceptions. We co=
uld rewrite those destructors, but that would involve changes in behavior t=
hat would require a larger version bump, compared to the minor version upda=
te we are tasked with.</div><div><br></div><div>We have determined that the=
 destructors in question are safe to mark noexcept(false). In the worst cas=
e, this will preserve these destructors&#39; intended behavior.</div><div><=
br></div><div>In order to implement this, we now have to test with all the =
compiler versions that we support, and figure out=C2=A0in which versions=C2=
=A0(1) noexcept is not supported, or (2) noexcept is supported AND=C2=A0we =
must use it to preserve behavior.</div><div><br></div><div>We will probably=
 end up implementing a macro defined based on a number of #if defined(...) =
conditions. With some compilers, we will be able to use the value of the __=
cplusplus macro to determine that noexcept is supported and required. With =
other compilers -=C2=A0most prominently,=C2=A0MSVC 2015 -=C2=A0noexcept(fal=
se) is required to preserve behavior AND avoid a compiler warning,=C2=A0BUT=
 __cplusplus remains defined as 199711. In this case, we need to test condi=
tionally for the MSVC compiler version.</div><div><br></div><div>One might =
argue that MS should bump their __cplusplus macro to at least 201103. Howev=
er,=C2=A0this would break code that depends on C++11 features that MSVC doe=
s not implement. It is in fact sound that MSVC defines their __cplusplus ma=
cro with the old value, as long as not <em>all</em> C++11 features are yet =
supported.</div><div><br></div><div>This then suggests that future C++ vers=
ions could benefit from a way to test for the presence of individual featur=
es, because at least <em>some</em> implementations are likely to have parti=
al support for the new language version.</div><div><br></div><div>I can env=
ision two ways to do this:</div><div><br></div><div>- Explicitly.</div><div=
><br></div><div>In this case, each individual new language feature should c=
ome with an accompanying macro that an implementation can enable to indicat=
e support for that feature. For example, there could be lots of standard ma=
cros such as: __noexcept_supported</div><div><br></div><div>- Generically. =
</div><div><br></div><div>In this case, a library author could embed sentin=
el code that may or may not compile; however, a failure would not produce=
=C2=A0a warning or an error. Instead, successful compilation of=C2=A0the co=
de snippet would lead to conditional behavior. Example:</div><div><br></div=
><div>#test</div><div>void f() noexcept {}</div><div>#if noerrors</div><div=
>#define MYLIBRARY_NOEXCEPT(X) noexcept(X)</div><div>#else</div><div>#defin=
e MYLIBRARY_NOEXCEPT(X)</div><div>#endif</div><div>#endtest</div><div><br><=
/div><div>In the example above, #test starts a sentinel code block which ha=
s local scope (implied anonymous namespace), which may or may not compile, =
and ends with the next preprocessor directive. Then, special operators &quo=
t;noerrors&quot; and &quot;nowarnings&quot; are available for use in #if an=
d #elif, and remain=C2=A0available=C2=A0until #endtest.</div><div><br></div=
><div>I understand everyone hates macros and the preprocessor in general. H=
owever, adapting code to multiple compilers is a problem that the language =
doesn&#39;t solve in any other way.</div><div><br></div><div>It seems to me=
 that sentinel compilation via preprocessor directives would be a useful an=
d generic way to solve this issue.</div><div><br></div><div><br></div></div=
>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_3_96256940.1437932577617--
------=_Part_2_1561314666.1437932577617--

.