为什么MATLAB会抛出“太多的输出参数"?我超载subsref(下标的引用)时出错? [英] Why does MATLAB throw a "too many output arguments" error when I overload subsref (subscripted reference)?

查看:614
本文介绍了为什么MATLAB会抛出“太多的输出参数"?我超载subsref(下标的引用)时出错?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为玩具示例,我有一个仅将矢量或矩阵包装在对象中并包含创建时间的时间戳的类.我正在尝试重载subsref以便

As a toy example, I have a class that simply wraps a vector or matrix in an object and includes a timestamp of when it was created. I'm trying to overload subsref so that

  1. ()引用的工作原理与标准向量和矩阵类型完全相同
  2. {}引用与()引用完全一样的工作方式(换句话说,与单元格无关)
  3. .引用使我可以访问对象的 private 属性以及其他在技术上不是属性的字段.
  1. () referencing works exactly as it does with the standard vector and matrix types
  2. {} referencing works in exactly the same way as () referencing (nothing to do with cells in other words)
  3. . referencing allows me to access the private properties of the object and other fields that aren't technically properties.

代码:

classdef TimeStampValue

    properties (Access = private)
        time;
        values;
    end

    methods
        %% Constructor
        function x = TimeStampValue(values)
            x.time = now();
            x.values = values;
        end

        %% Subscripted reference
        function x = subsref(B, S)
            switch S.type
                case '()'
                    v = builtin('subsref', B.values, S);
                    x = TimeStampValue(v);
                case '{}'
                    S.type = '()';
                    v = builtin('subsref', B.values, S);
                    x = TimeStampValue(v);
                case '.'
                    switch S.subs
                        case 'time'
                            x = B.time;
                        case 'values'
                            x = B.values;
                        case 'datestr'
                            x = datestr(B.time);
                    end
            end
        end

        function disp(x)
            fprintf('\t%d\n', x.time)
            disp(x.values)
        end   

    end

end

但是,大括号{}引用不起作用.我运行这段代码

However brace {} referencing doesn't work. I run this code

clear all
x = TimeStampValue(magic(3));
x{1:2}

我得到这个错误:

Error using TimeStampValue/subsref
Too many output arguments.
Error in main (line 3)
x{1:2} 

MException.last给了我这个信息:

identifier: 'MATLAB:maxlhs'
   message: 'Too many output arguments.'
     cause: {0x1 cell}
     stack: [1x1 struct]

这没有帮助,因为异常堆栈中唯一的东西是包含我在上面运行的三行代码的文件.

which isn't helpful because the only thing in the exception stack is the file containing three lines of code that I ran above.

我在subsref的switch语句的第一行上放置了一个断点,但是MATLAB从未到达断点.

I placed a breakpoint on the first line of the switch statement in subsref but MATLAB never reaches it.

这是怎么回事? ().引用都可以正常工作,为什么{}引用不起作用?

Whats the deal here? Both () and . referencing work as you would expect, so why doesn't {} referencing work?

推荐答案

重载花括号{}以返回与平时不同的输出参数数时,还必须重载numel以返回预期的数字(在这种情况下为1). 更新:从 R2015b 开始,新功能 修改nargout和nargin以进行索引的页面方法" .摘录:

When overloading the curly braces {} to return a different number of output arguments than usual, it is also necessary to overload numel to return the intended number (1, in this case). UPDATE: As of R2015b, the new function numArgumentsFromSubscript was created to be overloaded instead of numel. The issue remains the same, but this function should be overloaded instead of numel as I describe in the original answer below. See also the page "Modify nargout and nargin for Indexing Methods". Excerpt:

当类重载numArgumentsFromSubscript时,MATLAB调用此方法而不是numel来计算subsref nargoutsubsasgn nargin所需的参数数量.

When a class overloads numArgumentsFromSubscript, MATLAB calls this method instead of numel to compute the number of arguments expected for subsref nargout and subsasgn nargin.

如果类没有重载numArgumentsFromSubscript,则MATLAB会调用numel来计算nargoutnargin的值.

If classes do not overload numArgumentsFromSubscript, MATLAB calls numel to compute the values of nargout or nargin.

下面是对潜在问题的更多说明(需要指定输出参数的数量).

More explanation of the underlying issue (need to specify number of output arguments) follows.

原始答案(对于R2015b +,使用numArgumentsFromSubscript代替numel)

Original answer (use numArgumentsFromSubscript instead of numel for R2015b+)

为处理使用花括号索引时用逗号分隔的输出参数列表的可能性,MATLAB调用numel,以根据输入索引的大小确定输出参数的数量(根据

To handle the possibility of a comma separated list of output arguments when indexing with curly braces, MATLAB calls numel to determine the number of output arguments from the size of the input indexes (according to this MathWorks answer). If the number of output arguments in the definition of overloaded subsref is inconsistent with (i.e. less than) the number provided by numel, you get the "Too many output arguments" error. As stated by MathWorks:

因此,要允许大括号索引到您的对象中,同时返回与输入大小不符的多个参数,您将需要在类目录中重载NUMEL函数.

Therefore, to allow curly brace indexing into your object while returning a number of arguments INCONSISTENT with the size of the input, you will need to overload the NUMEL function inside your class directory.

由于x{1:2}通常提供两个输出(X{1},X{2}),因此定义function x = subsref(B, S)与此输入不兼容.解决方案是在类中包括一个简单的numel方法以重载内置函数,如下所示:

Since x{1:2} normally provides two outputs (X{1},X{2}), the definition function x = subsref(B, S) is incompatible for this input. The solution is to include in the class a simple numel method to overload the builtin function, as follows:

function n = numel(varargin)
    n = 1;
end

现在{}索引可以按预期工作,模仿():

Now the {} indexing works as intended, mimicking ():

>> clear all % needed to reset the class definition
>> x = TimeStampValue(magic(3));
>> x(1:2)
ans = 
    7.355996e+05
     8     3
>> x{1:2}
ans = 
    7.355996e+05
     8     3

但是,以这种方式使花括号超载显然是一种特定类型我们[MathWorks]没想到客户会写的代码". MathWorks建议:

However, overloading curly braces in this manner is apparently a "specific type of code that we [MathWorks] did not expect customers to be writing". MathWorks recommends:

如果将类设计为仅输出一个参数,则不建议您使用大括号索引,这需要重载NUMEL.相反,建议您使用平滑的brace()索引.

If you are designing your class to output only one argument, it is not recommended that you use curly brace indexing that requires you to overload NUMEL. Instead, it is recommended you use smooth brace () indexing.

更新:有趣的是, R2015b发行说明状态:

在MATLAB发布R2015b之前,对于一些返回或分配给逗号分隔列表的索引表达式,MATLAB错误地计算了subsref输出和subsasgn输入的预期参数数量.

Before MATLAB release R2015b, MATLAB incorrectly computed the number of arguments expected for outputs from subsref and inputs to subsasgn for some indexing expressions that return or assign to a comma-separated list.

在版本R2015b中,MATLAB根据索引表达式所需的参数数量正确计算nargoutnargin的值.

With release R2015b, MATLAB correctly computes the values of nargout and nargin according to the number of arguments required by the indexing expression.

那么也许现在已经解决了?

So perhaps this is now fixed?

想到的另一种解决方案是将function x = subsref(B, S)更改为function varargout = subsref(B, S)并添加varargout=cell(1,numel(B)); varargout{1} = x;.正如Amro在评论中指出的那样,必须预先分配单元格,以避免出现有关未分配参数的错误.

An alternative solution that comes to mind is to change function x = subsref(B, S) to function varargout = subsref(B, S) and adding varargout=cell(1,numel(B)); varargout{1} = x;. As Amro noted in comments, pre-allocating the cell is necessary to avoid an error about an unassigned argument.

这篇关于为什么MATLAB会抛出“太多的输出参数"?我超载subsref(下标的引用)时出错?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆