运算符 () 的"explicit"和"implicit"调用之间的区别
Difference between "explicit" and "implicit" invocation of operator ()
标准中是否有描述从基类调用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函数和函子函数的行为是相同的。
Compiler is clang 3.6.
"隐式"调用也是格式错误的。事实上,GCC拒绝了它,所以它看起来像是Clang中的一个bug。
标准(N4140, [over.call]/1)明确规定
对于类型为
T
的类对象x
,如果T::operator()(T1, T2, T3)
存在并且操作符被重载解析机制(13.3.3)选为最佳匹配函数,则调用x(arg1,...)
将被解释为x.operator()(arg1, ...)
。
所以两个调用的行为必须相同。
更新:这是Clang中已知的问题。
相关文章:
- 如何防止clang格式在流运算符调用之间添加换行符<<
- DirectX 9 在重置调用之间保留状态
- Vulkan是否需要在多个具有透明度的平局调用之间进行同步
- 静态模板类成员函数的这两个调用之间有什么区别?
- 在cython调用之间保持数据帧的状态
- C++:cout 和函数调用之间的计算顺序
- unix中选择和轮询系统调用之间的功能差异
- 如何在函数调用之间存储 deque 值
- 如何在c/c++中使函数调用之间的变量值持久化
- 连接线程(阻塞调用线程直到线程终止)和普通函数调用之间的区别是什么
- GDI - 是否可以在WM_PAINT调用之间将位图保存在内存中
- C++ 数字库:std::uniform_int_distribution<>,更改调用之间的分布边界
- 来自托管库的调用之间本机库中静态变量的值
- 按引用调用和按指针调用之间的差异
- 链式静态函数调用之间的参数求值顺序
- 对伪随机数生成器的相同调用之间的不同行为
- 在来自C++应用程序的成功调用之间保留dll中的状态
- 如何在c++ dll中实例化一个类,使它在函数调用之间保持内存
- 我可以在函数调用之间在c++ DLL中维护内存吗?
- 带和不带()的构造函数调用之间的区别