if条件で宣言された変数の非典型的な使用法を示す例を次に示します。
変数のタイプはint &
、ブール値に変換可能で、thenおよびelseブランチで使用できます。
#include <string>
#include <map>
#include <vector>
using namespace std;
vector<string> names {"john", "john", "jack", "john", "jack"};
names.push_back("bill"); // without this push_back, my g++ generated exe fails :-(
map<string, int> ages;
int babies = 0;
for (const auto & name : names) {
if (int & age = ages[name]) {
cout << name << " is already " << age++ << " year-old" << endl;
} else {
cout << name << " was just born as baby #" << ++babies << endl;
++age;
}
}
出力は
john was just born as baby #1
john is already 1 year-old
jack was just born as baby #2
john is already 2 year-old
jack is already 1 year-old
bill was just born as baby #3
残念ながら、条件内の変数は「=」宣言構文でのみ宣言できます。
これにより、明示的なコンストラクターを持つ型の他の有用なケースが除外されます。
たとえば、を使用した次の例std::ifstream
はコンパイルされません...
if (std::ifstream is ("c:/tmp/input1.txt")) { // won't compile!
std::cout << "true: " << is.rdbuf();
} else {
is.open("c:/tmp/input2.txt");
std::cout << "false: " << is.rdbuf();
}
2019年1月に編集...説明したことをエミュレートできるようになりました...
これは、C++11 の ifstream のような移動可能なクラスに対して機能し、C++17 以降のコピー省略を伴うコピー不可能なクラスに対しても機能します。
2019 年 5 月編集: auto を使用して冗長性を軽減
{
if (auto is = std::ifstream ("missing.txt")) { // ok now !
std::cout << "true: " << is.rdbuf();
} else {
is.open("main.cpp");
std::cout << "false: " << is.rdbuf();
}
}
struct NoCpy {
int i;
int j;
NoCpy(int ii = 0, int jj = 0) : i (ii), j (jj) {}
NoCpy(NoCpy&) = delete;
NoCpy(NoCpy&&) = delete;
operator bool() const {return i == j;}
friend std::ostream & operator << (std::ostream & os, const NoCpy & x) {
return os << "(" << x.i << ", " << x.j << ")";
}
};
{
auto x = NoCpy(); // ok compiles
// auto y = x; // does not compile
if (auto nocpy = NoCpy (7, 8)) {
std::cout << "true: " << nocpy << std::endl;
} else {
std::cout << "false: " << nocpy << std::endl;
}
}