私はboost::fusion::mapを使用するいくつかのクラスを書いています。以下に、簡略化されたコードを示します。
template <typename ObjDef>
struct Object
{
typedef
typename
boost::fusion::result_of::as_map<valid_list_of_fusion_pairs>::type map_type;
map_type map;
Object()
: map()
{}
Object(Object const & other)
: map(other.map)
{}
Object & operator=(Object const & other)
{
map = other.map;
return *this;
}
// non-const version
template <typename FieldId>
typename
boost::fusion::result_of::at_key<map_type, FieldId>::type get()
{
return boost::fusion::at_key<FieldId>(map);
}
// const version
template <typename FieldId>
typename
boost::fusion::result_of::at_key<map_type const, FieldId>::type get() const
{
return boost::fusion::at_key<FieldId>(map);
}
};
および別のクラス:
template <typename Obj, typename FieldId>
class Field
{
private:
Obj &obj_m;
public:
// type returned by \c operator()
typedef
typename
boost::fusion::result_of::at_key<typename Obj::map_type, FieldId>::type return_type;
// type returned by \c operator() const
typedef
typename
boost::fusion::result_of::at_key<typename Obj::map_type const, FieldId>::type return_type_const;
Field(Obj &obj)
: obj_m(obj)
{ }
virtual ~Field()
{ }
return_type operator()()
{
return obj_m.template get<FieldId>();
}
return_type_const operator()() const
{
/*
* PROBLEM!
*/
Obj const & obj_const = obj_m;
return obj_const.template get<FieldId>();
}
};
「問題!」を探してください。上記のコードのコメントで。そのメソッドでは、コンパイラはメソッドのconst修飾子を無視し、非constバージョンのobj_m.get()を呼び出して、次のようなことを実行できるようにします。
obj_m.template get<FieldId>() = 10;
この方法はconstなので、これは正しくありません。次に、コンパイラにconstバージョンを呼び出させるために、obj_mへのconst参照が宣言されます。今文
obj_const.template get<FieldId>() = 0;
コンパイルエラーが発生します。これまでのところ、これは現在の方法では問題ではありませんが、定数の正確性には不便であり、明らかに望ましくありません。
なぜこれが起こっているのか考えていますか?ありがとう!