Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;'的语法理解问题;使用'; 我阅读了一些用C++创建的项目的技术文档。我发现一行代码包含我不懂的语法: using c = char (& (cClass::* [1]) (cClass(*)[2]) &)[3];_C++ - Fatal编程技术网

C++;'的语法理解问题;使用'; 我阅读了一些用C++创建的项目的技术文档。我发现一行代码包含我不懂的语法: using c = char (& (cClass::* [1]) (cClass(*)[2]) &)[3];

C++;'的语法理解问题;使用'; 我阅读了一些用C++创建的项目的技术文档。我发现一行代码包含我不懂的语法: using c = char (& (cClass::* [1]) (cClass(*)[2]) &)[3];,c++,C++,我在这里看到使用关键字的。这意味着我们要处理一个别名,但这一行做什么呢?我怎么能理解呢?我认为这会创建一个命名别名c,并将右侧表达式的结果赋给它。但是这个表达式是什么呢?下面是如何一步一步地读取您的类型。 为了清楚起见,下面我们声明一个变量x T x[1] x是类型为T cClass::* x[1] x是指向cClass内部成员的指针数组(长度为1) V (cClass::* x[1]) (U) x是指向cClass内部成员函数的指针数组(长度为1)。所述成员函数将U作为参数,并返回V V

我在这里看到使用关键字的
。这意味着我们要处理一个别名,但这一行做什么呢?我怎么能理解呢?我认为这会创建一个命名别名
c
,并将右侧表达式的结果赋给它。但是这个表达式是什么呢?

下面是如何一步一步地读取您的类型。 为了清楚起见,下面我们声明一个变量
x

T x[1]
x
是类型为
T

cClass::* x[1]
x
是指向
cClass
内部成员的指针数组(长度为1)

V (cClass::* x[1]) (U)
x
是指向
cClass
内部成员函数的指针数组(长度为1)。所述成员函数将
U
作为参数,并返回
V

V (cClass::* x[1]) (U) &
x
是指向
cClass
内部成员函数的指针数组(长度为1)。所述成员函数以
U
为参数,返回
V
,只能对左值调用

V & (cClass::* x[1]) (U) &
V (& (cClass::* x[1]) (U) &)[3]
x
是指向
cClass
内部成员函数的指针数组(长度为1)。所述成员函数以
U
为参数,返回对-
V
的引用,并且只能对左值调用

V & (cClass::* x[1]) (U) &
V (& (cClass::* x[1]) (U) &)[3]
x
是指向
cClass
内部成员函数的指针数组(长度为1)。所述成员函数以
U
为参数,返回对
V
数组(长度3)的引用,并且只能对左值调用

V & (cClass::* x[1]) (U) &
V (& (cClass::* x[1]) (U) &)[3]
最后,要得到你的实际类型

char (& (cClass::* x[1]) (cClass(*)[2]) &)[3]
我们选择
V=char
U=(cClass(*)[2])
,后者是指向
cClass
的数组(长度2)的指针

V (cClass::* x[1]) (U)
更具可读性的备选方案:

using char3 = char [3];
using ptrTo2cClass = cClass(*)[2];
using ptrToMethod = char3 & (cClass::*) (ptrTo2cClass) &;
using c = ptrToMethod[1];

类型必须从中间开始解释(如果是变量声明,则变量名应该是中间的)。你向右走,直到到达终点。然后向左,直到你点击开头的
)。此时你要么解释了整个类型(然后你就完成了),要么你在
(…)
的内部,在这种情况下,你丢弃它们并重复相同的过程(向右,然后向左)

由于这不是一个变量声明,您首先需要找到变量名的位置(如果它是一个变量名的话)。直观地说这更容易(一旦您获得了一些经验),但是一个不错的经验法则是从左边开始,直到您点击
,或者
(…)
,或者
[…]

知道了这一点,我们可以将其转换为变量声明。我添加了
x
作为变量名:

char (& (cClass::*x[1]) (cClass(*)[2]) &)[3];
现在我们可以开始读取类型了。首先我们向右走:
x
变量
x
是…
x[1]
一个包含1个元素的数组,包含…
(没有其他东西在右边,向左走。)
cClass::*x[1]
指向类
cClass
成员的指针,类型为…
(类::*x[1])
(左边没有其他内容,跳过括号。)
(cClass::*x[1])(………)&
一个带有一些参数的函数,
&
-qualified1,返回…
(没有其他东西在右边,向左走。)
&(类::*x[1])(………)&
对…
(&(类::*x[1])(………)&)
(左边没有其他内容,跳过括号。)
(&(C类::*x[1])(………)&[3]
一个包含3个元素的数组,包含……
char(&(类::*x[1])(………)&[3]
char
s

我们结束了。函数参数的类型(
cClass(*)[2]
)必须使用相同的过程单独解释。它是“指向大小为2的数组的指针,包含
cClass
es”



1函数参数右侧的
&
表示只能在左值上调用它(函数是“
&
-qualified”)。

缩小范围后,我刚刚看到了两个答案。然而,我确实写了一个新的答案,因为它展示了一种替代方法,你可以用STL类型的特征来缩小范围,从外部到内部

#include <type_traits>
#include <typeinfo>
#include <iostream>

class cClass {};

template <typename T>
struct Extract : std::false_type {};

template <typename TRet, typename TArg>
struct Extract<TRet (cClass::*)(TArg) &> : std::true_type {
    using Ret = TRet;
    using Arg = TArg;
};

int main()
{
    using Type = char(&(cClass::* [1])(cClass(*)[2])&)[3];
    std::cout << "Type=" << typeid(Type).name() << '\n';
    static_assert(std::is_array_v<Type>);
    using Type1 = decltype(std::declval<Type>()[0]);
    std::cout << "array[" << std::extent_v<Type> << "] of " << typeid(Type1).name() << '\n';
    static_assert(std::is_reference_v<Type1>);
    using Type2 = decltype(std::remove_reference_t<Type1>());
    std::cout << "ref to " << typeid(Type2).name() << '\n';
    static_assert(std::is_member_function_pointer_v<Type2>);
    std::cout << "member function pointer, cClass, taking " << typeid(Extract<Type2>::Arg).name() << ", returning " << typeid(Extract<Type2>::Ret).name() << '\n';

    using FuncParam = cClass(*)[2];                 // Pointer to array of 2 cClass
    using FuncRet = char(&)[3];                     // Reference to array of 3 chars
    using Func = FuncRet(cClass::*)(FuncParam) &;   // Member function for lvalue of cClass, taking FuncParam, returning FuncRet
    using FuncArrayOne = Func[1];                   // Array with one Func (WTF?)
    static_assert(std::is_same_v<FuncArrayOne, Type>);

    return 0;
}
#包括
#包括
#包括
类{};
模板
结构提取:std::false_type{};
模板
结构提取:std::true\u类型{
使用Ret=TRet;
使用Arg=TArg;
};
int main()
{
使用Type=char(&(类::*[1])(类(*)[2])&[3];

std::cout注意:这是我在上的答案的改编,因此我将其标记为社区维基,以避免获得重复的信誉点。(当然,如果您喜欢这个答案,请随意向上投票。)

下面的基于C++的模板允许编译器自己为您分解此声明的结构。

#include <iostream>

template <typename T>
struct introspect;

template <>
struct introspect<char> {
    static std::ostream& prettyPrint(std::ostream& os) { return os << "char"; }
};

template <typename T>
struct introspect<T*> {
    static std::ostream& prettyPrint(std::ostream& os) {
        return os << "pointer to " << introspect<T>::prettyPrint;
    }
};

template <typename T>
struct introspect<T&> {
    static std::ostream& prettyPrint(std::ostream& os) {
        return os << "reference to " << introspect<T>::prettyPrint;
    }
};

template <typename T, typename Res, typename Arg1>
struct introspect<Res (T::*)(Arg1) &> {
    static std::ostream& prettyPrint(std::ostream& os) {
        return os << "pointer to lvalue member function of " << introspect<T>::prettyPrint
                  << " taking (" << introspect<Arg1>::prettyPrint
                  << ") and returning (" << introspect<Res>::prettyPrint << ')';
    }
};

template <typename T, std::size_t N>
struct introspect<T[N]> {
    static std::ostream& prettyPrint(std::ostream& os) {
        return os << "array of " << N << " (" << introspect<T>::prettyPrint << ")";
    }
};

class cClass;
template <>
struct introspect<cClass> {
    static std::ostream& prettyPrint(std::ostream& os) {
        return os << "cClass";
    }
};

int main() {
    using c = char (& (cClass::* [1]) (cClass(*)[2]) &)[3];
    std::cout << introspect<c>::prettyPrint << '\n';
    return 0;
}

在深入了解细节之前,让我告诉你们,<代码> [1 ] <代码>,代码> [ 2 ] <代码>,代码> > 3】/>代码>部分非常不寻常。这些真的是源代码,还是它们在文档中使用的“注释”,这些代码不意味着是C++代码?,但他们似乎很可疑,IMO。这行代码是在一个简单的主函数源代码中。开发人员将其描述为“使用指向成员函数的指针将其赋值给c”正如我所理解的,在阅读C++引用之后,指针指向1类方法。方法接受2个元素的数组,其中的类型作为指针指向类,但是在这样的表达式的两侧使用<代码>和<代码>运算符的目的是什么?最后?有人在故意装傻吗?池的回答解释了如何解读这一点,但诚实地说,即使是经验