这是在 C++03 中执行 "Expression SFINAE" 的有效方法吗?

Is this a valid way of performing "Expression SFINAE" in C++03?

在C++11中,SFINAE很容易判断一个表达式是否有效。例如,想象一下检查某些内容是否可流式传输:

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

print_if_possible 将仅参与 重载决议 如果 os << x 是一个格式正确的表达式。

live example on godbolt.org


我需要在 C++03 中做同样的事情,我发现 sizeof 可以提供帮助(因为我需要一个未评估的表达式上下文)。这是我想出的:

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


似乎 g++clang++ 的最新版本都接受带有 -std=c++03 -Wall -Wextrasizeof 版本.

SFINAE 表情有点灰。 C++03 基本上什么也没说。它既没有明确禁止也没有明确允许。当前的实现不允许这样的构造,因为它导致了大量的实现复杂性,并且不清楚它是否意味着被允许,CWG 是 at one point leaning towards banning it (see the April, 2003 note) before it eventually reversed course,部分是根据添加的 decltypeconstexpr到 C++11(参见 N2634 的介绍)。

这一切都发生在 CWG 开始明确标记其决议旨在追溯应用的问题的 DR 状态之前。

我认为最好的建议就是 "ask your compiler vendor"。在 C++11 模式下支持表达式 SFINAE 的编译器不太可能在 C++03 模式下取消该支持(供应商可能将 CWG 339 视为缺陷报告并追溯应用,或将其视为扩展)。 OTOH,一个从不支持 C++11 的编译器不太可能投入表达式 SFINAE 工作所需的大量成本(事实上,直到最近它才在某个主要编译器 cough 中工作).我还怀疑仍然使用 15 年历史的语言的地方不太可能使用此类支持所需的现代工具链。