【发布时间】:2023-02-01 03:51:57
【问题描述】:
在尝试 This post 的答案时, 最终得到以下代码:
#include <iostream>
#include <typeinfo>
namespace Test
{
struct MyPtr
{
double operator, (int Input)
{
std::cout << "Operator, called" << std::endl;
return 1.0;
}
MyPtr operator* ()
{
std::cout << "operator* called" << std::endl;
return *this ;
}
MyPtr operator++ ()
{
std::cout << "operator++ called" << std::endl;
return *this;
}
MyPtr operator!= (const MyPtr& Other)
{
std::cout << "operator!= called" << std::endl;
return *this;
}
};
struct Foo
{
MyPtr Ptr;
};
MyPtr begin(Foo& t)
{
return t.Ptr;
}
MyPtr end(Foo& t)
{
return t.Ptr;
}
}
int main()
{
std::cout << typeid(decltype(++begin(std::declval<Test::Foo&>()),
*begin(std::declval<Test::Foo&>()),
std::true_type{})).name() <<std::endl;
}
产生:
d
这里,d 来自逗号运算符。然而,由于 decltype 说明符中的最后一个表达式是 std::true_type{},为什么 decltype 说明符解析为逗号运算符返回的类型而不是 std::true 类型。
我的理论是 std::true_type 可以隐式转换为 int,此处的 operator,() 作为参数,因此 decltype 表达式等效于:
std::cout << typeid(decltype(++begin(std::declval<Test::Foo&>()),
declval<double&>())).name() <<std::endl;
你能确认这是正确的吗?
当我更好地了解编译器的行为时,我打算做什么,我计划用以下内容替换 decltype 说明符的内容:
std::cout << typeid(decltype(void(++begin(std::declval<Test::Foo&>())),
void(*begin(std::declval<Test::Foo&>())),
std::true_type{})).name() <<std::endl;
这将阻止 operator,() 匹配,即使它被覆盖。你也可以确认这是正确的吗?
【问题讨论】:
-
通过实际评估表达式而不是仅在未评估的上下文中使用它们,您可以更容易地看到会发生什么
-
正如那个Demo。
-
如果一个操作数是
void(..),那么确实没有使用用户提供的逗号运算符。 -
好吧,我明白为什么我的回答是错误的,但我现在无法修复它。稍后会回来。
标签: c++ c++11 typetraits decltype comma-operator