web-dev-qa-db-ja.com

obj-cで単純な「min」メソッドをどのように定義しますか

Utilsクラスでminメソッドとmaxメソッドを定義したいと思います。

_@interface Utils

int min(int a, int b);
int max(int a, int b);

@end
_

しかし、名前付きパラメーターは必要ありません。重すぎる表記になります。 Cスタイルの定義を使いたかったのです。ただし、呼び出しとしての[Utils min(a, b)]は機能しません。私の問題は何ですか?

助けてくれてありがとう

21
Fred Polack

Objective-cのOSX実装を使用していないため、事前定義されたMINおよびMAXマクロにアクセスできない可能性があります。

これらは自分で次のように定義できます

#define MIN(a,b)    ((a) < (b) ? (a) : (b))
#define MAX(a,b)    ((a) > (b) ? (a) : (b))

それらを定義するためのより良い方法はおそらくありますが、これらはあなたが使用するための単純なマクロを作成します。クラスが通常共有する一般的な.hファイルにそれらを追加できます。

18
Brandon Bodnar

すでにマクロとして定義されています。

MIN(a, b)

MAX(a, b)

これらを再定義する必要はありません。

62
Mongus Pong

BrandonBodnárによって投稿されたソリューションには重大な問題があります(この記事の執筆時点では、有効なソリューションとしてマークされています)。

ここで説明されている問題: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Min-and-Max.html そしてそれに対する(有効で安全な)解決策:- http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Typeof.html

自分でチェックしてください:

#include <stdio.h>

#define NAIVE_MAX(a,b) (a > b ? a : b)

#define NAIVE_MIN(a,b) (a < b ? a : b)

#if !defined MAX
#define MAX(a,b) \
({ __typeof__ (a) __a = (a); \
__typeof__ (b) __b = (b); \
__a > __b ? __a : __b; })
#endif

#if !defined MIN
#define MIN(a,b) \
({ __typeof__ (a) __a = (a); \
__typeof__ (b) __b = (b); \
__a < __b ? __a : __b; })
#endif

int main (int argc, const char * argv[]) {
    int a = 3;
    int b = 5;

#pragma mark NON-FATAL CASES:
    printf("NAIVE_MAX(%d, %d) => %d\n", a, b, NAIVE_MAX(a, b));
    printf("NAIVE_MIN(%d, %d) => %d\n", a, b, NAIVE_MIN(a, b));

    printf("MAX(%d, %d) => %d\n", a, b, MAX(a, b));
    printf("MIN(%d, %d) => %d\n", a, b, MIN(a, b));

    printf("\nEverything fine so far...\n\n");

#pragma mark FATAL CASES:
    //cache:
    int _a = a;
    int _b = b;
    printf("NAIVE_MAX(%d++, %d++) => %d\n", _a, _b, NAIVE_MAX(a++, b++));

    //reset:
    a = _a;
    b = _b;
    printf("NAIVE_MIN(%d++, %d++) => %d\n", _a, _b, NAIVE_MIN(a++, b++));

    //reset:
    a = _a;
    b = _b;
    printf("NAIVE_MAX(++%d, ++%d) => %d\n", _a, _b, NAIVE_MAX(++a, ++b));

    //reset:
    a = _a;
    b = _b;
    printf("NAIVE_MIN(++%d, ++%d) => %d\n", _a, _b, NAIVE_MIN(++a, ++b));

    printf("\nOuch, this doesn't look right at all!\n\n");

#pragma mark NON-FATAL CASES:
    //reset:
    a = _a;
    b = _b;
    printf("MAX(%d++, %d++) => %d\n", _a, _b, MAX(a++, b++));

    //reset:
    a = _a;
    b = _b;
    printf("MIN(%d++, %d++) => %d\n", _a, _b, MIN(a++, b++));

    //reset:
    a = _a;
    b = _b;
    printf("MAX(++%d, ++%d) => %d\n", _a, _b, MAX(++a, ++b));

    //reset:
    a = _a;
    b = _b;
    printf("MIN(++%d, ++%d) => %d\n", _a, _b, MIN(++a, ++b));

    printf("\nAh, much better now.\n\n");

    return 0;
}

コンソールログ:

NAIVE_MAX(3, 5) => 5
NAIVE_MIN(3, 5) => 3
MAX(3, 5) => 5
MIN(3, 5) => 3

Everything fine so far...

NAIVE_MAX(3++, 5++) => 6
NAIVE_MIN(3++, 5++) => 4
NAIVE_MAX(++3, ++5) => 7
NAIVE_MIN(++3, ++5) => 5

Ouch, this doesn't look right at all!

MAX(3++, 5++) => 5
MIN(3++, 5++) => 3
MAX(++3, ++5) => 6
MIN(++3, ++5) => 4

Ah, much better now.

したがって、上記のコードに見られるように(そしてBrandonBodnárによって提案されたように、申し訳ありませんがバディ;)​​)、最悪の事態を避けたい場合は、単純な実装を使用しないでくださいこのような場合。

30
Regexident

これはおそらくこの特定のアプリケーションにとっては良い考えではありませんが、「名前なし」のパラメーターを使用して、または長さゼロの名前を使用してObjective-Cメソッドを作成することは可能性ありです。

_+ min:(int)a :(int)b;
...
[Utils min:a :b]
_

(セレクターは@selector(min::)になります。)

7
Kevin Reid

Objective-Cクラスのメソッドは、名前付きパラメーター、期間を使用します。仕方ないよ。

グローバルで無料の関数にしてみませんか?この種のことのためにUtilsクラスは必要ないはずです。

グローバル名前空間を乱雑にしたくない場合は、Objective-C++を使用して(すべての.mファイルの名前を.mmに変更)、名前空間に配置できます。

2

「XXIntegerMath.h」という名前のテンプレートファイルにこれをドロップします...

#import <Foundation/Foundation.h>

static inline NSInteger imax(NSInteger a, NSInteger b) {
    return  a > b ? a : b;
}

static inline NSInteger imin(NSInteger a, NSInteger b) {
    return  a < b ? a : b;
}

次に、Objective-cクラスで.。

#import "XXIntegerMath.h"
NSInteger minValue = imin(someValue, someOtherValue);

Regexidentによって説明された問題に悩まされることはありません。

0
TJez