Is this a valid way of performing "Expression SFINAE" in C++03? [duplicate]
Asked Answered
A

1

9

In C++11, it is easy to SFINAE on whether or not an expression is valid. As an example, imagine checking if something is streamable:

template <typename T>
auto print_if_possible(std::ostream& os, const T& x) 
    -> decltype(os << x, void());

print_if_possible will only participate in overload resolution if os << x is a well-formed expression.

live example on godbolt.org


I need to do the same in C++03, and I figured out that sizeof could help (as I needed an unevaluated context for an expression). This is what I came up with:

template <int> struct sfinaer { };

template <typename T>
void print_if_possible(std::ostream& os, const T& x, 
    sfinaer<sizeof(os << x)>* = NULL);

live example on godbolt.org


It seems that both the latest versions of g++ and clang++ accept the sizeof version with -std=c++03 -Wall -Wextra.

  • Is the code guaranteed to work as intended in C++03?

  • Is it correct to conclude that any usage of C++11 expression SFINAE can be backported to C++03 using sfinaer and sizeof?

Acidity answered 26/9, 2018 at 9:53 Comment(5)
Why do you put , 0 inside sizeof? Do you need it in this particular example?Florie
@Evg: no need for that, removed.Acidity
sfinaer is a nice name.Botticelli
Thinking about your question... if the expression is a bit-field, you'll need , 0 in sizeof.Florie
There might be a little side effect if <expression>.operator,(0) is invalid.Strapping
P
2

Expression SFINAE is a bit gray. C++03 basically said nothing on the subject. It neither explicitly banned it nor explicitly allowed it. Contemporary implementations did not permit such constructs because it caused substantial implementation complexity and it's unclear whether it's meant to be allowed, and CWG was at one point leaning towards banning it (see the April, 2003 note) before it eventually reversed course, partially in light of decltype and constexpr that were added to C++11 (see the introduction to N2634).

This also all happened well before CWG started explicitly marking the DR status of issues whose resolutions are meant to apply retroactively.

I think the best advice here is simply "ask your compiler vendor". A compiler that supports expression SFINAE in its C++11 mode is unlikely to tear out that support in C++03 mode (the vendor may treat CWG 339 as a defect report and apply it retroactively, or consider it as an extension). OTOH, a compiler that never supported C++11 is unlikely to invest the substantial costs necessary for expression SFINAE to work (indeed, it did not work in a certain major compiler cough until relatively recently). I also suspect that a place still stuck with an 15-year-old language is unlikely to use the modern toolchains necessary for such support.

Podiatry answered 27/9, 2018 at 5:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.