【问题标题】:Difference between "explicit" and "implicit" invocation of operator ()运算符()的“显式”和“隐式”调用之间的区别
【发布时间】:2015-08-18 15:12:47
【问题描述】:

标准中是否有条款描述从基类调用operator () 的方式之间的以下区别?

#include <iostream>
#include <type_traits>

#include <cstdlib>
#include <cassert>

template< typename visitor, typename ...visitors >
struct composite_visitor
    : std::decay_t< visitor >
    , composite_visitor< visitors... >
{

    //using std::decay_t< visitor >::operator ();
    //using composite_visitor< visitors... >::operator ();

    composite_visitor(visitor && _visitor, visitors &&... _visitors)
        : std::decay_t< visitor >(std::forward< visitor >(_visitor))
        , composite_visitor< visitors... >{std::forward< visitors >(_visitors)...}
    { ; }

};

template< typename visitor >
struct composite_visitor< visitor >
    : std::decay_t< visitor >
{

    //using std::decay_t< visitor >::operator ();

    composite_visitor(visitor && _visitor)
        : std::decay_t< visitor >(std::forward< visitor >(_visitor))
    { ; }

};

template< typename visitor, typename ...visitors >
composite_visitor< visitor, visitors... >
compose_visitors(visitor && _visitor, visitors &&... _visitors)
{
    return {std::forward< visitor >(_visitor), std::forward< visitors >(_visitors)...};
}

int
main()
{
    struct A {};
    struct B {};
#if 1
    struct { int operator () (A) { return 1; } } x;
    struct { int operator () (B) { return 2; } } y;
    auto xy = compose_visitors(x, y);
#else
    auto xy = compose_visitors([] (A) { return 1; }, [] (B) { return 2; });
#endif
    // "implicit":
    assert(xy(A{}) == 1);
    assert(xy(B{}) == 2);
    // "explicit":
    assert(xy.operator () (A{}) == 1); // error: member 'operator()' found in multiple base classes of different types
    assert(xy.operator () (B{}) == 2);
    return EXIT_SUCCESS;
}

“隐式”调用编译得很好,但不是“显式”。为什么会这样?

compose_visitors 通过构造从所有参数派生的类,将参数组合成单个类。

取消注释 using 指令会删除硬错误。很清楚。

lambda 函数和仿函数的行为是相同的。

编译器是clang 3.6

【问题讨论】:

  • 你可以清理一堆:不需要 ctors,不需要花哨的衰减或创建函数,只需要两个带有 () 的类和一个派生类。如果你清理它,@yakk 我 +1。

标签: c++ c++11 inheritance c++14


【解决方案1】:

“隐式”调用也是格式错误的。事实上,GCC rejects it,所以它看起来像是 Clang 中的一个错误。

标准 (N4140, [over.call]/1) 明确指出

如果 T::operator()(T1, T2, T3) 存在并且运算符被重载解析机制 (13.3.2) 选为最佳匹配函数,则调用 x(arg1,...) 被解释为 x 类型为 T 的类对象 x.operator()(arg1, ...)。 3).

所以两个调用的行为必须相同。

更新:这是 Clang 中的 known issue

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-23
    • 2013-05-19
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 2017-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多