【问题标题】:std::result_of applied to const overloaded methodsstd::result_of 应用于 const 重载方法
【发布时间】:2017-01-19 16:32:08
【问题描述】:

如果我给了

typedef std::vector<int> v;

那么下面可以用来捕获常量迭代器的类型(另一种方法是使用v::const_iterator,但这取决于在类中显式定义的const_iterator成员类型。

typedef typename std::result_of<decltype(&v::cbegin)(v*)>::type const_iterator;

确实,我们可以检查上面的内容是否如我们所愿。

static_assert(std::is_same<const_iterator, typename v::const_iterator>::value);

但是,我在下面发现编译器失败。

typedef typename std::result_of<decltype(&v::begin)(v*)>::type iterator;

编译器抱怨该方法被重载(通过 const 修饰符)并且无法明确解决。但是,我找不到解决歧义的语法。至少,人们希望下面的内容是明确的,因为只有 const 版本才能对 const 对象进行操作。然而,即使是下面的也同样有问题。

typedef typename std::result_of<decltype(&v::begin)(const v*)>::type const_iterator2;

如何引用特定的 const 或 nonconst 版本的 begin?

【问题讨论】:

    标签: c++ static constants typedef decltype


    【解决方案1】:

    以下是你想要的:

    using v = std::vector<int>;
    using iter = decltype(std::declval<v>().begin());
    static_assert(std::is_same<iter, typename v::iterator>::value);
    

    这里的问题是&amp;v::begin 是模棱两可的。 v::begin 函数有两个,&amp; 运算符无法知道返回哪一个的地址。使用std::declval 可以解决这个问题。由于std::declval&lt;v&gt;() 的返回类型是v,编译器知道你对非const v::begin() 感兴趣。

    同样,以下为您提供 const 版本:

    using citer = decltype(std::declval<const v>().begin());
    static_assert(std::is_same<citer, typename v::contst_iterator>::value);
    

    请注意,此代码中未创建任何对象。 std::declval 没有定义,所以它只适用于像 decltype 这样未经评估的上下文。

    【讨论】:

    • 我理解这个响应,但是为什么上面v* 参数的const 修饰符不能解决歧义?
    • std::declval&lt;v&gt;() 的返回类型不是v
    • @epl 因为&amp; 在查看参数之前已经尝试并未能获取不明确的函数名称的地址。
    • @skypjack 是的,从技术上讲它是 std::add_rvalue_reference&lt;T&gt;::type,所以 v&amp;&amp; 表示非常量,const v&amp; 表示 const,但我觉得这些细节并不相关。
    猜你喜欢
    • 1970-01-01
    • 2020-04-20
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 2015-07-18
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多