C++ STL mapに対するboost::assignのstatic_cast

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
chibago

C++ STL mapに対するboost::assignのstatic_cast

#1

投稿記事 by chibago » 12年前

表題のとおりですが、以下のコードが動かなくて困っております。
(GCC環境です。)

コード:

#ifndef __DATA_H_
#define __DATA_H_

#include <map>
#include <string>
#include <iostream>
#include <boost/assign/list_of.hpp>

class Data{

 public:
  Data();
  void print_data();
 private:
  std::map<int, std::string> map_data; 

};

#endif

#include "Data.h"

Data::Data(): map_data(static_cast<std::map<int, std::string> &>
		      (boost::assign::map_list_of<int, std::string>(1, "taro")
                        (2, "jiro")
		       (3, "saburo"))){}


void Data:: print_data(){
  std::cout<<this->map_data[1]<<std::endl;
}

エラーは

Data.cpp: コンストラクタ ‘Data::Data()’ 内:
Data.cpp:6:23: エラー: invalid static_cast from type ‘boost::assign_detail::generic_list<std::pair<int, std::basic_string<char> > >’ to type ‘std::map<int, std::basic_string<char> >&’

と言うようなものです。一応、解説ですが、通るコンパイラもあるようですが、GCC環境では
boost::assignでメンバ変数の初期化を行おうとすると、型が不鮮明との趣旨のエラーが出てしまうため、
あえてstatic_castで変換します。(この掲示板でご指摘いただきました。)なお、vector等ではこのスタイル
は問題なく通ります。

なお、本命としては、メンバ変数はconstにしたいのですが、constにした場合は初期化だけのコードは
問題なく通り、データを参照する関数(ここではprint_data)を付け加えると以下のようなエラーになります。

Data.cpp: コンストラクタ ‘Data::Data()’ 内:
Data.cpp:6:23: エラー: invalid static_cast from type ‘boost::assign_detail::generic_list<std::pair<int, std::basic_string<char> > >’ to type ‘std::map<const int, std::basic_string<char> >&’
Data.cpp: メンバ関数 ‘void Data::print_data()’ 内:
Data.cpp:10:30: エラー: passing ‘const std::map<int, std::basic_string<char> >’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = int, _Tp = std::basic_string<char>, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::basic_string<char> > >, std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::basic_string<char>, std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’ discards qualifiers [-fpermissive]

お分かりになる方がいらっしゃりましたら、コメントをいただければ幸いです。

アバター
a5ua
記事: 199
登録日時: 13年前

Re: C++ STL mapに対するboost::assignのstatic_cast

#2

投稿記事 by a5ua » 12年前

>static_cast<std::map<int, std::string> &>
constが抜けていませんか?(static_cast<const std::map<int, std::string> &>)


メンバをconstにした場合の話ですが、
std::mapのoperator[]は、constメンバ関数ではないので、

コード:

void hoge(const std::map<int, std::string> &m)
{
	std::cout << m[1] << std::endl;	// エラー:operator[]はconstメンバ関数ではない
}
のようなことはできません。

C++0x(C++11となるようですが)では、std::mapにatというメンバ関数が追加されます
この関数は、keyに対応するvalueへの参照を返すが、keyが存在しないときにはout_of_range例外を投げます。

コード:

void hoge(const std::map<int, std::string> &m)
{
	std::cout << m.at(1) << std::endl;	// 1が登録されていない場合、例外を投げる
}
これが使えない状況ならば、同等の機能を持つ関数を自作すればよいでしょう

コード:

template <typename K, typename V, typename P, typename A>
const V &get_value(const std::map<K, V, P, A> &m, const K &key)
{
	typename std::map<K, V, P, A>::const_iterator it = m.find(key);
	if (it == m.end()) throw std::out_of_range("invalid key");
	return it->second;
}
void hoge(const std::map<int, std::string> &m)
{
	std::cout << get_value(m, 1) << std::endl;	// 1が登録されていない場合、例外を投げる
}

chibago

Re: C++ STL mapに対するboost::assignのstatic_cast

#3

投稿記事 by chibago » 12年前

a5uaさん
ありがとうございました。
ご指摘の通りです。

てっきり、static_castの型宣言のconstはメンバ変数の宣言に合わせるものだと思い込んでおりました。
勉強し直します。

STLコンテナのオペレータがconstではないものがあるのは驚きました。

以前の私のプログラムには、constなど高級な修飾はなかったのですが、
STLのmapのキーに自作コンテナを設定しようとした際に、
ソートの関係で比較演算子を付けなければならないと分かったのですが、
さらに、constでなければならないとわかり困惑したことを覚えております。

それ以来、私のプログラムにもできるだけconstをつけておりますが、
結構な労力となっております。(ただ、堅固なプログラムになった様で、
眺めている分には爽快ではありますが)

その流れで考えるとmapの[]がconstではないというのは、
ある意味裏切られた気分です。

アドバイス大変参考になりました。
ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る