回答編集履歴

7

文章ちょっと修正

2017/03/20 07:10

投稿

raccy
raccy

スコア21737

test CHANGED
@@ -1,4 +1,4 @@
1
- 結論
1
+ Chironianさんのコメントからの結論
2
2
 
3
3
 
4
4
 

6

結論だけ書いた

2017/03/20 07:09

投稿

raccy
raccy

スコア21737

test CHANGED
@@ -1,3 +1,97 @@
1
+ 結論
2
+
3
+
4
+
5
+ ```C++
6
+
7
+ #include <iostream>
8
+
9
+ class ComplexInt
10
+
11
+ {
12
+
13
+ private:
14
+
15
+ int real;
16
+
17
+ int imag;
18
+
19
+
20
+
21
+ public:
22
+
23
+ ComplexInt(int real, int imag = 0) : real(real), imag(imag) {}
24
+
25
+ friend ComplexInt operator+(const ComplexInt &x, const ComplexInt &y)
26
+
27
+ {
28
+
29
+ return ComplexInt(x.real + y.real, x.imag + y.imag);
30
+
31
+ }
32
+
33
+ friend std::ostream &operator<<(std::ostream &os, const ComplexInt &ci)
34
+
35
+ {
36
+
37
+ os << ci.real;
38
+
39
+ if (ci.imag >= 0) {
40
+
41
+ os << "+";
42
+
43
+ }
44
+
45
+ os << ci.imag << "i";
46
+
47
+ return os;
48
+
49
+ }
50
+
51
+ };
52
+
53
+
54
+
55
+
56
+
57
+ int main()
58
+
59
+ {
60
+
61
+ const ComplexInt a(2, 3);
62
+
63
+ const ComplexInt b(1, -5);
64
+
65
+ std::cout << a << std::endl;
66
+
67
+ std::cout << b << std::endl;
68
+
69
+ std::cout << (a + b) << std::endl;
70
+
71
+ std::cout << (a + 1) << std::endl;
72
+
73
+ std::cout << (1 + a) << std::endl;
74
+
75
+ return 0;
76
+
77
+ }
78
+
79
+ ```
80
+
81
+
82
+
83
+ 何も問題なし、以上。
84
+
85
+
86
+
87
+ 以下、駄文。
88
+
89
+
90
+
91
+ ---
92
+
93
+
94
+
1
95
  C++がだめな理由を考えました。
2
96
 
3
97
 

5

補足を追加

2017/03/20 07:05

投稿

raccy
raccy

スコア21737

test CHANGED
@@ -480,7 +480,11 @@
480
480
 
481
481
 
482
482
 
483
- C++で何か嫌だと思う点の一つは、メンバー関数として実装できないことだと思います。オブジェクト指向原理主義者からみると、メソッドでない奴は駄目な奴だと勘違いしているのかも知れません。Scalaの暗黙の型変換もさほど変わらないと思うのですが、objectのメソッドだからいいとか言い出すのでしょうか…。
483
+ C++で何か嫌だと思う点の一つは、メンバー関数として実装できないことだと思います。オブジェクト指向原理主義者からみると、メソッドでない奴は駄目な奴だと勘違いしているのかも知れません。Scalaの暗黙の型変換もさほど変わらないと思うのですが、objectのメソッドだからいいとか言い出すのでしょうか…。
484
+
485
+
486
+
487
+ ※ friendsだとできるそうです。追記しています。
484
488
 
485
489
 
486
490
 

4

崩れてた

2017/03/20 04:26

投稿

raccy
raccy

スコア21737

test CHANGED
@@ -464,6 +464,8 @@
464
464
 
465
465
  }
466
466
 
467
+ ```
468
+
467
469
 
468
470
 
469
471
  では、これで一安心だねっていうかと思うと、ちょっと使っただけで、グローバルに動作を影響を与えています。あ、Scalaと暗黙の型変換を検索するところと検索の仕方だけは同じ所に戻っただけのようです。

3

C\+\+フレンズ

2017/03/20 04:17

投稿

raccy
raccy

スコア21737

test CHANGED
@@ -487,3 +487,125 @@
487
487
 
488
488
 
489
489
  最後にHaskellを見てみましょう。Haskellの`a + b`は`(+)(a)(b)`です。他の関数と同じようにオーバーロードできます。オブジェクト指向なんかにして、無理にメソッドとかメンバー関数とか、そんなことをするより、全部関数にしておけば良かったのかも知れません。
490
+
491
+
492
+
493
+ ---
494
+
495
+
496
+
497
+ 君はC++が得意なフレンズなんだね。
498
+
499
+
500
+
501
+ ```C++
502
+
503
+ #include <iostream>
504
+
505
+ class ComplexInt
506
+
507
+ {
508
+
509
+ private:
510
+
511
+ int real;
512
+
513
+ int imag;
514
+
515
+
516
+
517
+ public:
518
+
519
+ ComplexInt(int real, int imag) : real(real), imag(imag) {}
520
+
521
+ ComplexInt operator+(const ComplexInt &other) const
522
+
523
+ {
524
+
525
+ return ComplexInt(real + other.real, imag + other.imag);
526
+
527
+ }
528
+
529
+ ComplexInt operator+(int other) const
530
+
531
+ {
532
+
533
+ return ComplexInt(real + other, imag);
534
+
535
+ }
536
+
537
+ std::string toString() const
538
+
539
+ {
540
+
541
+ std::string str("");
542
+
543
+ str += std::to_string(real);
544
+
545
+ if (imag >= 0) {
546
+
547
+ str += "+";
548
+
549
+ }
550
+
551
+ str += std::to_string(imag) += "i";
552
+
553
+ return str;
554
+
555
+ }
556
+
557
+ int getReal() const { return real; }
558
+
559
+ int getImag() const { return imag; }
560
+
561
+ friend std::ostream &operator<<(std::ostream &os, const ComplexInt &ci)
562
+
563
+ {
564
+
565
+ os << ci.toString();
566
+
567
+ return os;
568
+
569
+ }
570
+
571
+ friend ComplexInt operator+(int x, const ComplexInt &y)
572
+
573
+ {
574
+
575
+ return ComplexInt(x, 0) + y;
576
+
577
+ }
578
+
579
+ };
580
+
581
+
582
+
583
+
584
+
585
+ int main()
586
+
587
+ {
588
+
589
+ const ComplexInt a(2, 3);
590
+
591
+ const ComplexInt b(1, -5);
592
+
593
+ std::cout << a << std::endl;
594
+
595
+ std::cout << b << std::endl;
596
+
597
+ std::cout << (a + b) << std::endl;
598
+
599
+ std::cout << (a + 1) << std::endl;
600
+
601
+ std::cout << (1 + a) << std::endl;
602
+
603
+ return 0;
604
+
605
+ }
606
+
607
+ ```
608
+
609
+
610
+
611
+ メンバー関数にできたけど、これこれで、ありなんだそうです。C++書くのつかれた。

2

名前空間を追加

2017/03/20 04:15

投稿

raccy
raccy

スコア21737

test CHANGED
@@ -124,7 +124,11 @@
124
124
 
125
125
 
126
126
 
127
- グローバル空間を汚すことは**行儀が悪いコード**と言われます。しかし、C++の演算子オーバーロードではグローバル関数として定義せざるをえない場合があります。
127
+ グローバル空間を汚すことは**行儀が悪いコード**と言われます(つまり、Cだと関数一個も作れないと言うこと)。しかし、C++の演算子オーバーロードではグローバル関数として定義せざるをえない場合があります
128
+
129
+
130
+
131
+ ※ 名前空間は汚す必要ない!って話なので、名前空間を汚さないの後から追記しています。
128
132
 
129
133
 
130
134
 
@@ -236,7 +240,7 @@
236
240
 
237
241
 
238
242
 
239
- ぱっと、C++とは違ってグローバル関数を使ってないですので、グローバルを汚すと言うことはしていないように思えます。しかし、暗黙の型変換も暗黙のクラスもグローバルに影響を与えています。ただ、足し算という処理は一つにまとめることができますので、C++よりはマシであると言えるのではないでしょうか。
243
+ ぱっと、C++とは違ってグローバル関数を使ってないですので、グローバルを汚すと言うことはしていないように思えます。しかし、暗黙の型変換も暗黙のクラスもグローバルに影響を与えています。**どっちにしろグローバルを汚します。**ただ、足し算という処理は一つにまとめることができますので、C++よりはマシであると言えるのではないでしょうか。
240
244
 
241
245
 
242
246
 
@@ -339,3 +343,147 @@
339
343
 
340
344
 
341
345
  この仕組みの利点は、グローバルを汚さないということです。他の型と動作が変わったわけではありません。しかし、欠点として、もともとの定義がcoerceを考慮していなければなりません。実質使えるのは数値のみです。
346
+
347
+
348
+
349
+ ---
350
+
351
+
352
+
353
+ 名前空間を汚さなくても大丈夫だそうです。
354
+
355
+
356
+
357
+ ```C++
358
+
359
+ #include <iostream>
360
+
361
+ namespace ci {
362
+
363
+ class ComplexInt
364
+
365
+ {
366
+
367
+ private:
368
+
369
+ int real;
370
+
371
+ int imag;
372
+
373
+
374
+
375
+ public:
376
+
377
+ ComplexInt(int real, int imag) : real(real), imag(imag) {}
378
+
379
+ ComplexInt operator+(const ComplexInt &other) const
380
+
381
+ {
382
+
383
+ return ComplexInt(real + other.real, imag + other.imag);
384
+
385
+ }
386
+
387
+ ComplexInt operator+(int other) const
388
+
389
+ {
390
+
391
+ return ComplexInt(real + other, imag);
392
+
393
+ }
394
+
395
+ std::string toString() const
396
+
397
+ {
398
+
399
+ std::string str("");
400
+
401
+ str += std::to_string(real);
402
+
403
+ if (imag >= 0) {
404
+
405
+ str += "+";
406
+
407
+ }
408
+
409
+ str += std::to_string(imag) += "i";
410
+
411
+ return str;
412
+
413
+ }
414
+
415
+ int getReal() const { return real; }
416
+
417
+ int getImag() const { return imag; }
418
+
419
+ };
420
+
421
+
422
+
423
+ std::ostream &operator<<(std::ostream &os, const ComplexInt &ci)
424
+
425
+ {
426
+
427
+ os << ci.toString();
428
+
429
+ return os;
430
+
431
+ }
432
+
433
+ ComplexInt operator+(int x, const ComplexInt &y)
434
+
435
+ {
436
+
437
+ return ComplexInt(x, 0) + y;
438
+
439
+ }
440
+
441
+ }
442
+
443
+
444
+
445
+ int main()
446
+
447
+ {
448
+
449
+ const ci::ComplexInt a(2, 3);
450
+
451
+ const ci::ComplexInt b(1, -5);
452
+
453
+ std::cout << a << std::endl;
454
+
455
+ std::cout << b << std::endl;
456
+
457
+ std::cout << (a + b) << std::endl;
458
+
459
+ std::cout << (a + 1) << std::endl;
460
+
461
+ std::cout << (1 + a) << std::endl;
462
+
463
+ return 0;
464
+
465
+ }
466
+
467
+
468
+
469
+ では、これで一安心だねっていうかと思うと、ちょっと使っただけで、グローバルに動作を影響を与えています。あ、Scalaと暗黙の型変換を検索するところと検索の仕方だけは同じ所に戻っただけのようです。
470
+
471
+
472
+
473
+ ---
474
+
475
+
476
+
477
+ ぶっちゃけ、C++とScalaでは、単にScalaは暗黙の型変換とか使えば、実装が少なくて済むので楽だよね、程度しか無いと思います。ただ、C++の方が細かく実装できる分、コストがー、コストがー、と言っている深淵を覗くことが大好きな人達には好まれるでしょう。
478
+
479
+
480
+
481
+ C++で何か嫌だと思う点の一つは、メンバー関数として実装できないことだと思います。オブジェクト指向原理主義者からみると、メソッドでない奴は駄目な奴だと勘違いしているのかも知れません。Scalaの暗黙の型変換もさほど変わらないと思うのですが、objectのメソッドだからいいとか言い出すのでしょうか…。
482
+
483
+
484
+
485
+ あと、たぶん、何か嫌だと思ってしまうのは、標準型に新たなメンバー関数を追加しているように見えると言うことではないでしょうか。じゃあ、ScalaやRubyはどうなのかというと、確かに、元々の標準型に何かを追加している訳ではありませんが、一歩離れれば、やっていることはさほどかわりありません。やり方が違うだけで目くじら立てるのはどうなのかとは思ってしまいます。
486
+
487
+
488
+
489
+ 最後にHaskellを見てみましょう。Haskellの`a + b`は`(+)(a)(b)`です。他の関数と同じようにオーバーロードできます。オブジェクト指向なんかにして、無理にメソッドとかメンバー関数とか、そんなことをするより、全部関数にしておけば良かったのかも知れません。

1

左辺!左辺!左辺!

2017/03/20 04:05

投稿

raccy
raccy

スコア21737

test CHANGED
@@ -128,7 +128,7 @@
128
128
 
129
129
 
130
130
 
131
- 対して、Scalaでは暗黙の型変換を定義できるため、次のようになります。
131
+ 対して、Scalaでは左辺も含めた暗黙の型変換を定義できるため、次のようになります。
132
132
 
133
133
 
134
134