LoginSignup
0
0

More than 5 years have passed since last update.

Effective C++ Third version, sample code compile list(3)Use const whenever possible.

Last updated at Posted at 2018-06-19

Effective C++: 55 Specific Ways to Improve Your Programs and DesignsThird version by Scott Mayers
https://www.informit.com/store/effective-c-plus-plus-55-specific-ways-to-improve-your-9780321334879
https://www.amazon.com/dp/0321334876

Sample code from
Yuzhen11/Effective_CPP
https://github.com/Yuzhen11/Effective_CPP

目的(purpose)

"Effective C++コンパイル記録は、コンパイラおよび対応標準により、コンパイルエラーMessageの違いを記録し、どのエラーが出たら、どの対応標準にすればエラーが少なくなるかを考察するための資料の第一歩です。
上記参照サイトにはコンパイルする仕組みを提供していない。簡易な台本(script)を作成する。

成果(outcome)

計画(plan)

(1)コンパイラの種類、対応標準の違いによってエラーの数が違う。
(2)同じエラー、警告であってもMessageの表現が違う。
(3) エラー、警告のMessageをネットで検索する際に役立てる。
(4)コード断片の役に立つまたは意味のあるコンパイル・リンク・実行エラーの取り方を検討する
(5)コード断片の役に立つまたは意味のある出力を検討する

結果(result)現在整理中

1) コンパイラによるエラー、渓谷の違い
2) コンパイラによる必要なヘッダファイルの違い
3) 参考にした資料

算譜(source code)

ec3.cpp
///Effective C++:  55 Specific Ways to Improve Your Programs and DesignsThird version by Scott Mayers
///https://www.informit.com/store/effective-c-plus-plus-55-specific-ways-to-improve-your-9780321334879
#include <iostream>
#include <cstdlib>

using namespace std;

const char * msg ="Item 3: Use const whenever possible.";

/// From here "Effective C++

//const keyword is remarkably versatile.

//For pointers, you can specify whether the pointer itself is const, the data it points to is const, both, or neither:

char greeting[] = "Hello";
char* p = greeting;  // non-const pointer, non-const data
const char* p = greeting;  // non-const pointer, const data
char* const p = greeting;  // const pointer, non-const data
const char* const p = greeting;  // const pointer, const data
//Declaring an iterator const is like declaring a pointer const (T * const pointer), the iterator isn't allow to point to something different, but the thing it points to may be modified.

const std::vector<int>::iterator iter = vec.begin();
*iter = 10; // ok
++iter;  // error

std::vector<int>::const_iterator cIter = vec.begin();
*cIter = 10;  // error
++iter;  // fine
//Return value can be const. Help to reduce the incidence of client errors without giving up safety or efficiency.

class Rational { ... };
const Rational operator*(const Rational& lhs, const Rational& rhs);

Rational a, b, c;
(a*b) = c; // error
if (a*b = c) ...    // good to prevent this error, can be identified during compilation
//We can easily prevent the above mistakes. What we want is if (a*b == c)

//We can also have const member functions

class TextBlock {
public:
    const char& operator[](std::size_t position) const 
    { return text[position]; }
    char& operator[](std::size_t position)
    { return text[position]; }
private:
    std::string text;
};

TextBlock tb("Hello");
std::cout << tb[0];  // call non-const operator[]
const TextBlock ctb("World");
std::cout << ctb[0];  // call the const one

tb[0] = 'x';  // ok
ctb[0] = 'x';  // error
Will be met when we pass parameter using reference-to-const.

//Bitwise const and logical const

//Compilers enforce bitwise const, but we need logical const!

class CTextBlock {
public:
    char& operator[](std::size_t position) const  // inappropriate but bitwise const 
    { return pText[position]; }
};
//Really want to modify value in const member function? mutable!

//Avoid Duplicatoin in const and Non-const Member Functions

class TextBlock {
public:
    const char& operator[](std::size_t position) const 
    { return text[position]; }
    char& operator[](std::size_t position)
    {
        return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
    }
private:
    std::string text;
};
//But I don't this is a good idea...

//Things to Remember

//Declaring something const helps compilers detect usage errors. const can be applied to objects at any cope, to function parameters and return types, and to member functions as a whole.

//Copmilers enforce bitwise constness, but you should program using conceptual constness.

//When const and non-const member functions have essentially identical implementations, code duplicatoin can be avoided by having the non-const version call the const version.


/// to here from "Effective C++"

int main() {
  cout << msg << endl;
  return EXIT_SUCCESS;
}

編纂・実行結果(compile and go)

cpa.sh
$$ ../c1.sh ec3
$ clang++ ec3.cpp  -std=c++2a -Wall
ec3.cpp:18:13: error: redefinition of 'p' with a different type: 'const char *' vs 'char *'
const char* p = greeting;  // non-const pointer, const data
            ^
ec3.cpp:17:7: note: previous definition is here
char* p = greeting;  // non-const pointer, non-const data
      ^
ec3.cpp:19:13: error: redefinition of 'p' with a different type: 'char *const' vs 'char *'
char* const p = greeting;  // const pointer, non-const data
            ^
ec3.cpp:17:7: note: previous definition is here
char* p = greeting;  // non-const pointer, non-const data
      ^
ec3.cpp:20:19: error: redefinition of 'p' with a different type: 'const char *const' vs 'char *'
const char* const p = greeting;  // const pointer, const data
                  ^
ec3.cpp:17:7: note: previous definition is here
char* p = greeting;  // non-const pointer, non-const data
      ^
ec3.cpp:23:12: error: implicit instantiation of undefined template 'std::__1::vector<int, std::__1::allocator<int> >'
const std::vector<int>::iterator iter = vec.begin();
           ^
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/iosfwd:200:28: note: template is declared here
class _LIBCPP_TEMPLATE_VIS vector;
                           ^
ec3.cpp:23:25: error: use of class template 'iterator' requires template arguments
const std::vector<int>::iterator iter = vec.begin();
                        ^
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/iterator:521:29: note: template is declared here
struct _LIBCPP_TEMPLATE_VIS iterator
                            ^
ec3.cpp:23:41: error: use of undeclared identifier 'vec'
const std::vector<int>::iterator iter = vec.begin();
                                        ^
ec3.cpp:24:2: error: C++ requires a type specifier for all declarations
*iter = 10; // ok
 ^
ec3.cpp:25:1: error: expected unqualified-id
++iter;  // error
^
ec3.cpp:27:6: error: implicit instantiation of undefined template 'std::__1::vector<int, std::__1::allocator<int> >'
std::vector<int>::const_iterator cIter = vec.begin();
     ^
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/iosfwd:200:28: note: template is declared here
class _LIBCPP_TEMPLATE_VIS vector;
                           ^
ec3.cpp:27:42: error: use of undeclared identifier 'vec'
std::vector<int>::const_iterator cIter = vec.begin();
                                         ^
ec3.cpp:28:2: error: C++ requires a type specifier for all declarations
*cIter = 10;  // error
 ^
ec3.cpp:29:1: error: expected unqualified-id
++iter;  // fine
^
ec3.cpp:32:22: error: expected member name or ';' after declaration specifiers
class Rational { ... };
                     ^
ec3.cpp:36:3: error: expected ')'
(a*b) = c; // error
  ^
ec3.cpp:36:1: note: to match this '('
(a*b) = c; // error
^
ec3.cpp:36:2: error: C++ requires a type specifier for all declarations
(a*b) = c; // error
 ^
ec3.cpp:37:1: error: expected unqualified-id
if (a*b = c) ...    // good to prevent this error, can be identified during compilation
^
ec3.cpp:52:1: error: unknown type name 'TextBlock'
TextBlock tb("Hello");
^
ec3.cpp:53:6: error: no type named 'cout' in namespace 'std'
std::cout << tb[0];  // call non-const operator[]
~~~~~^
ec3.cpp:53:11: error: expected unqualified-id
std::cout << tb[0];  // call non-const operator[]
          ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.

算譜(source code)

ec3.cpp

///Effective C++:  55 Specific Ways to Improve Your Programs and DesignsThird version by Scott Mayers
///https://www.informit.com/store/effective-c-plus-plus-55-specific-ways-to-improve-your-9780321334879
#include <iostream>
#include <cstdlib>
#include <vector>

using namespace std;

const char * msg ="Item 3: Use const whenever possible.";

/// From here "Effective C++

//const keyword is remarkably versatile.

//For pointers, you can specify whether the pointer itself is const, the data it points to is const, both, or neither:

char greeting[] = "Hello";
char* p1 = greeting;  // non-const pointer, non-const data /// change name p to p1
const char* p2 = greeting;  // non-const pointer, const data/// change name p to p2
char* const p3 = greeting;  // const pointer, non-const data /// change name p to p3
const char* const p4 = greeting;  // const pointer, const data ///change name p to p4
//Declaring an iterator const is like declaring a pointer const (T * const pointer), the iterator isn't allow to point to something different, but the thing it points to may be modified.///change name p to p5

void f() { /// add {}
  vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};/// add definition vec
  const std::vector<int>::iterator iter = vec.begin();
  *iter = 10; // ok
///++iter;  // error ///ec3.cpp:28:1: error: cannot increment value of type 'const std::vector<int>::iterator' (aka 'const __wrap_iter<int *>')


  std::vector<int>::const_iterator cIter = vec.begin();
/// *cIter = 10;  // error ///ec3.cpp:31:8: error: cannot assign to return value because function 'operator*' returns a const value
  ++iter;  // fine
//Return value can be const. Help to reduce the incidence of client errors without giving up safety or efficiency.
}/// add {}

class Rational {
///...
};
const Rational operator*(const Rational& lhs, const Rational& rhs);

void h() {
  Rational a, b, c;
/// (a*b) = c; // error ec3.cpp:43:7: error: no viable overloaded '='
  if (a*b = c)
  }
/// ...    // good to prevent this error, can be identified during compilation
//We can easily prevent the above mistakes. What we want is if (a*b == c)

//We can also have const member functions

class TextBlock {
public:
  const char& operator[](std::size_t position) const
  {
    return text[position];
  }
  char& operator[](std::size_t position)
  {
    return text[position];
  }
private:
  std::string text;
};

void g() {
  TextBlock tb("Hello");
  std::cout << tb[0];  // call non-const operator[]
  const TextBlock ctb("World");
  std::cout << ctb[0];  // call the const one

  tb[0] = 'x';  // ok
  ctb[0] = 'x';  // error
//Will be met when we pass parameter using reference-to-const.
}
//Bitwise const and logical const

//Compilers enforce bitwise const, but we need logical const!

class CTextBlock {
public:
  char& operator[](std::size_t position) const  // inappropriate but bitwise const
  {
    return pText[position];
  }
};
//Really want to modify value in const member function? mutable!

//Avoid Duplicatoin in const and Non-const Member Functions

class TextBlock {
public:
  const char& operator[](std::size_t position) const
  {
    return text[position];
  }
  char& operator[](std::size_t position)
  {
    return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
  }
private:
  std::string text;
};
//But I don't this is a good idea...

//Things to Remember

//Declaring something const helps compilers detect usage errors. const can be applied to objects at any cope, to function parameters and return types, and to member functions as a whole.

//Copmilers enforce bitwise constness, but you should program using conceptual constness.

//When const and non-const member functions have essentially identical implementations, code duplicatoin can be avoided by having the non-const version call the const version.


/// to here from "Effective C++"

int main() {
  f();
  g();
  cout << msg << endl;
  return EXIT_SUCCESS;
}

編纂・実行結果(compile and go)

cpa.sh
$ ../c1.sh ec3
$ clang++ ec3.cpp  -std=c++2a -Wall
ec3.cpp:33:1: error: cannot increment value of type 'const std::vector<int>::iterator' (aka 'const __wrap_iter<int *>')
++iter;  // fine
^ ~~~~
ec3.cpp:45:9: error: no viable overloaded '='
if (a*b = c)
    ~~~ ^ ~
ec3.cpp:37:7: note: candidate function (the implicit copy assignment operator) not viable: 'this' argument has type
      'const Rational', but method is not marked const
class Rational { 
      ^
ec3.cpp:37:7: note: candidate function (the implicit move assignment operator) not viable: 'this' argument has type
      'const Rational', but method is not marked const
ec3.cpp:46:1: error: expected statement
}
^
ec3.cpp:63:11: error: no matching constructor for initialization of 'TextBlock'
TextBlock tb("Hello");
          ^  ~~~~~~~
ec3.cpp:52:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char [6]'
      to 'const TextBlock' for 1st argument
class TextBlock {
      ^
ec3.cpp:52:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'const char [6]'
      to 'TextBlock' for 1st argument
class TextBlock {
      ^
ec3.cpp:52:7: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was
      provided
ec3.cpp:65:17: error: no matching constructor for initialization of 'const TextBlock'
const TextBlock ctb("World");
                ^   ~~~~~~~
ec3.cpp:52:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const char [6]'
      to 'const TextBlock' for 1st argument
class TextBlock {
      ^
ec3.cpp:52:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'const char [6]'
      to 'TextBlock' for 1st argument
class TextBlock {
      ^
ec3.cpp:52:7: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was
      provided
ec3.cpp:79:14: error: use of undeclared identifier 'pText'
    { return pText[position]; }
             ^
ec3.cpp:85:7: error: redefinition of 'TextBlock'
class TextBlock {
      ^
ec3.cpp:52:7: note: previous definition is here
class TextBlock {
      ^
7 errors generated.

参考資料(reference)

Effective C++(項1〜5)解説
https://qiita.com/MoriokaReimen/items/58f183d421bb932cbbda
Effective C++ Third version, sample code compile list(まとめ)
https://qiita.com/kaizen_nagoya/items/2092638c221e1033040c
docker gnu(gcc/g++) and llvm(clang/clang++)
https://qiita.com/drafts/059874ea39c4de64c0f7
[C][C++]の国際規格案の例題をコンパイルするときの課題7つ。
https://qiita.com/kaizen_nagoya/items/5f4b155030259497c4de
C++N4606 Working Draft 2016, ISO/IEC 14882, C++ standardのコード断片をコンパイルするためにしていること
https://qiita.com/kaizen_nagoya/items/a8d7ee2f2e29e76c19c1
コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da
Clang/Clang++(LLVM) gcc/g++(GNU) コンパイラ警告等比較
https://qiita.com/kaizen_nagoya/items/9a82b958cc3aeef0403f
C++2003とC++2017でコンパイルエラーになるならない事例集
https://qiita.com/kaizen_nagoya/items/a13ea3823441c430edff
Qiitaに投稿するCのStyle例(暫定)
https://qiita.com/kaizen_nagoya/items/946df1528a6a1ef2bc0d
cpprefjpのdecltypeをコンパイル試験
https://qiita.com/kaizen_nagoya/items/090909af702f0d5d8a67
MISRA C++ 5-0-16
https://qiita.com/kaizen_nagoya/items/7df2d4e05db724752a74
C++ Templates Part1 BASICS Chapter 3. Class Templates 3.2 Use of Class Template Stack stack1test.cpp
https://qiita.com/kaizen_nagoya/items/cd5fc49106fad5a4e9ed
ISO/IEC TS 17961:2013 C Secure Coding Rules(1) All list(to be confirmed)
https://qiita.com/kaizen_nagoya/items/54e056195c4f11b850a1
C言語(C++)に対する誤解、曲解、無理解、爽快。
https://qiita.com/kaizen_nagoya/items/3f3992c9722c1cee2e3a
C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識
https://qiita.com/kaizen_nagoya/items/d89a48c1536a02ecdec9
'wchar.h' file not found で困った clang++ macOS
https://qiita.com/kaizen_nagoya/items/de15cd46d657517fac11
Open POSIX Test Suiteの使い方を調べはじめました
https://qiita.com/kaizen_nagoya/items/644d5e407f5faf96e6dc
MISRA-C 2012 Referenceに掲載している文献の入手可能性を確認
https://qiita.com/kaizen_nagoya/items/96dc8b125e462d5575bb
どうやって MISRA Example Suiteをコンパイルするか
https://qiita.com/kaizen_nagoya/items/fbdbff5ff696e2ca7f00
MISRA C まとめ #include
https://qiita.com/kaizen_nagoya/items/f1a79a7cbd281607c7c9
「C++完全理解ガイド」の同意できること上位10
https://qiita.com/kaizen_nagoya/items/aa5744e0c4a8618c7671

文書履歴(document history)

ver. 0.10 初稿 20180619
ver. 0.11 参考文献追記 20180623

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0