1

boost::spirit::qi ルールを定義しました。

boost::spirit::qi::rule<Iterator, Identifier()> id;

ここで、識別子は次のように定義されます。

BOOST_STRONG_TYPEDEF(std::string, Identifier)

しかし、私が使用するとき

BOOST_SPIRIT_DEBUG_NODE(id);

次のエラーでコンパイルに失敗します。

boost_1_51_0/boost/spirit/home/support/attributes.hpp:1203: error: no match for 'operator<<' in 'out << val'

そして、ostream のオーバーロードされた演算子をリストします。

BOOST_STRONG_TYPEDEF が元の型へのキャスト演算子を定義していることを知っているので、コンパイラは Identifier から std::string に暗黙的にキャストすべきではありませんoperator<<か? または、コンパイラが他の演算子 (つまり ) と一致させようとしているときに、型のキャスト演算子を適用できないようにする制限はありoperator<<ますか?

次の演算子を定義すると、コンパイルされます。

inline std::ostream& operator<<(std::ostream& os, const Identifier& id)
{
    return os << static_cast<std::string const&>(id);
}

私はgcc4.4.2を使用しています

4

1 に答える 1

4

これは、boost、strong_typedef、または精神とは関係ありません。

これは、テンプレート引数の型推論に大きく関係しています。要するに、引数の型が推定されるとき、暗黙的な変換は決して行われません [1]

参照:

#include <iostream>
#include <string>
#include <boost/strong_typedef.hpp>

BOOST_STRONG_TYPEDEF(double, X)
int main() { std::cout << X(); }

問題ない!に置き換えるdoublestd::string、もう機能しません。何が違うの?

ストリーミング演算子の宣言が異なります。

対比

ostream& ostream::operator<<(double);

template<typename _CharT, typename _Traits, typename _Alloc>
   inline basic_ostream<_CharT, _Traits>&
   operator<<(basic_ostream<_CharT, _Traits>&, basic_string<_CharT, _Traits, _Alloc> const&)

演算子のオーバーロードが関数テンプレートであるという事実により、暗黙的な変換は許可されません。


[1]initializer_listここでは少し例外のように見えるかもしれません。話題は違いますが、

于 2013-01-31T23:10:30.337 に答える