質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1341閲覧

C++連想配列の定数ってどうやって定義してますか?私はClang-Tidyに警告されるような方法しか思いつきません。

jiro.kaihatsu

総合スコア15

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2022/06/04 11:25

編集2022/06/04 11:27

ソースファイルのローカル変数として連想配列の定数を作りたいのですが、Clang-Tidyにて警告の対象となってしまいます。

警告を受けないような連想配列の定数を作る方法はあるでしょうか。もし、これをご覧になった方で別の方法(連想配列で定数を定義する方法)をご存じの方は教えていただけませんか。

可能な限り、C++11の文法の範囲内を希望します。

サンプルコード

例えば、私のコードは次です。

c++11:FruitDatabase.cpp抜粋

1#include <unordered_map> 2#include "FruitDatabase.h" 3 4namespace { 5/* 6 * database変数はClang-Tidyの検査にて警告の対象となる。 7 * cert-err58-cpp 8 * Clang-Tidy: Initialization of 'database' with static storage duration may throw an exception that cannot be caught 9 */ 10 const std::unordered_map<int, std::string> database = { 11 {Fruit::Apple, "りんご"}, 12 {Fruit::Orange, "みかん"}, 13 {Fruit::Mango, "マンゴー"} 14 }; 15}

Clang-Tidyの警告

Clang-Tidyの警告内容は次です。

Clang-Tidy: Initialization of 'database' with static storage duration may throw an exception that cannot be caught

cert-err58-cppという警告のようです。

所感

コンパイルエラーになるわけではないし、警告されているような問題を回避する処置はするつもりなので、この警告を無視してしまうこともできますが、私が無知ゆえに知らないところで大きな問題になるのも嫌です。

参考

環境

  • C++11(GCC 4.8.5)
  • Tidy 15.0(CLionビルトイン)
  • Ubuntu 18.04

サンプルソース

c++11:FruitDatabaseクラス

1#include <unordered_map> 2 3#include "FruitDatabase.h" 4 5 6namespace { 7/* 8 * database変数はClang-Tidyの検査にて警告の対象となる。 9 * cert-err58-cpp 10 * Clang-Tidy: Initialization of 'database' with static storage duration may throw an exception that cannot be caught 11 */ 12 const std::unordered_map<int, std::string> database = { 13 {Fruit::Apple, "りんご"}, 14 {Fruit::Orange, "みかん"}, 15 {Fruit::Mango, "マンゴー"} 16 }; 17 18// これでも同じ警告である。 19// std::unordered_map<int, std::string> initialize() noexcept { 20// std::unordered_map<int, std::string> db; 21// try { 22// 23// } 24// catch (...) { 25// 26// } 27// return db; 28// } 29// 30// std::unordered_map<int, std::string> database = initialize(); 31} 32 33std::string FruitDatabase::name(Fruit::Code fruitCode) 34{ 35 auto it = database.find(fruitCode); 36 if (it != database.end()) { 37 return it->second; 38 } 39 return {}; 40} 41

c++11:Fruitクラス

1#pragma once 2 3 4class Fruit 5{ 6public: 7 enum Code { 8 Apple, 9 Orange, 10 Mango, 11 }; 12 13 explicit Fruit(Code code = Code::Apple) 14 : _code{code} 15 {} 16 17 static int toInt(Code code) { 18 return static_cast<int>(code); 19 } 20 21 int toInt() const { 22 Fruit::toInt(_code); 23 } 24 25 Code code() const { 26 return _code; 27 } 28 29private: 30 Code _code; 31};

c++11:利用

1#include <iostream> 2 3#include "Fruit.h" 4#include "FruitDatabase.h" 5 6/* 7 * Tidy cert_err58_cppのサンプル 8 */ 9int main(int argc, char **argv) 10{ 11 Fruit fruit{Fruit::Apple}; 12 auto fruit_name = FruitDatabase::name(fruit.code()); 13 std::cout << "name is " << fruit_name << std::endl; 14 15 return 0; 16} 17

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

どうしても警告を消したいなら、静的ローカル変数を使って遅延初期化しますかね。

c++

1const std::unordered_map<int, std::string>& GetDatabase() { 2 static std::unordered_map<int, std::string>* map; 3 if (!map) { 4 map = new std::unordered_map<int, std::string>({ 5 {Fruit::Apple, "りんご"}, 6 {Fruit::Orange, "みかん"}, 7 {Fruit::Mango, "マンゴー"} 8 }); 9 } 10 return *map; 11}

投稿2022/06/04 15:30

int32_t

総合スコア20909

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2022/06/04 15:36 編集

static std::unordered_map<int, std::string>* map = nullptr; // 初期化しといた方が無難な希ガス // static だからやんなくても無問題だろうけど...
jiro.kaihatsu

2022/06/05 13:52

どうもありがとうございました。参考にさせていただきます。
guest

0

const std::unordered_map<int, std::string> database = {

じゃなく、
const std::unordered_map<Fruit::Code, std::string> database = {
なのでは?

投稿2022/06/04 12:33

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jiro.kaihatsu

2022/06/05 13:52

はい、ご指摘のとおりです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問