【问题标题】:Excluding std::pair constructors that use explicit construction排除使用显式构造的 std::pair 构造函数
【发布时间】:2011-11-15 14:31:02
【问题描述】:

this answer 开始,似乎这些构造函数:

template<class U, class V> pair(pair<U, V>&& p); 
template<class U, class V> pair(const pair<U, V>& p);

在需要显式转换时禁止参与重载解决方案。

来自 C++11(§20.3.2,n3290):

备注:除非 U 可隐式转换为 first_type 且 V 可隐式转换为 second_type,否则此构造函数不应参与重载决议。

有人建议了一个有趣的SFINAE workaround,但这偏离了标准的文本。

如果没有一些特殊的内部编译器魔法,一个符合要求的实现如何可能将其排除在重载决议之外? IE。一个实现可以做到这一点,我可以为我自己的类型复制它吗?似乎没有任何符合这一点的方法!这是从 C++11 中删除概念的后遗症吗?

我确实想知道使用私有构造函数来执行 SFINAE 部分并从公共构造函数进行委托,但看起来构造函数委托参与 SFINAE 的方式并不能使该工作正常进行。

【问题讨论】:

  • “一个一致的实现怎么可能把它排除在重载决议之外?”魔法?
  • @R.MartinhoFernandes - 这似乎是唯一的方法 - 我希望不是这样,因为将大块标准标题变成魔法而不是我可以想象在要解决的实施优先事项列表中排名靠前。
  • 你有没有看过一些人是怎么做到的? gcc 似乎在 is_convertible 上使用 enable_if。
  • @PlasmaHH - 你是对的,当我看这个时,我发现我看错了标题。 gcc.gnu.org/bugzilla/show_bug.cgi?id=40925#c3 确实暗示它最初是打算通过概念来处理的。

标签: c++ c++11 sfinae


【解决方案1】:

但这偏离了标准的文本

允许实现向任何非虚拟库成员函数添加默认参数。这似乎恰好允许这种 SFINAE 技巧。

【讨论】:

  • 很有趣 - 我以前没有看到它拼写出来 - 它在哪里指定?它似乎也与链接的博客帖子状态相矛盾。
  • 在 17.6.5.5/2 中(根据我的 n3290 副本)。
  • 这对我来说很好地解决了这个问题 - 我想知道这是否是对规则的新放宽,但这可能与现在的原始问题有点远。
  • @awoodland :这不是新的,C++98 允许相同(以及模板类上的默认模板参数);这就是为什么前向声明任何标准库标识符总是非法的原因。
【解决方案2】:

我遗漏了两条信息:

  1. gcc 使用这个:

    template<class _U1, class _U2, class = typename
                   std::enable_if<std::is_convertible<_U1, _T1>::value
                                  && std::is_convertible<_U2, _T2>::value>::type>
            pair(_U1&& __x, _U2&& __y)
            : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
    

    诀窍似乎在于匿名@​​987654323@ 模板参数的默认值。我以前没见过,this implementation 也没用过。

  2. 我错过了 gcc 实际实现了这一点。

【讨论】:

  • 非类模板的默认模板参数是一个非常新的功能。使用它会将可移植性限制为 1 或 2 个编译器。六个月前甚至更少。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-16
  • 2022-07-20
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多