C++ 11には、以下のoperator<<
過負荷を追加しました:
template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<(basic_ostream<CharT,Traits>&& os,
const T& value);
これは、彼らが非const参照を取るためstd::ostream
sの右辺値参照をバインドすることはできません標準挿入オペレータに転送します。 std::declval<std::ostream>
がstd::ostream&&
を返すため、このオーバーロードが選択されているため、非常に許容されるインターフェイス(有効な基礎となる挿入演算子がない場合はSFINAEdが出力されません)のため、decltype
指定子が機能します。
単純な修正は、std::declval<std::ostream&>()
を使用することです。
main.cpp:8:39: error: invalid operands to binary expression ('std::basic_ostream<char>' and 'Foo')
std::declval<std::ostream&>() << std::declval<Foo>()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
:
typedef decltype(
std::declval<std::ostream&>() << std::declval<Foo>()
) foo_type;
クランは、この出力:テンプレートの過負荷があなたのdecltype
指定子と通常の挿入演算子オーバーロードによって選択されることはありませんので、それをコンパイルするためにこれが必要となり、std::ostream&
を返します。 Live Demo
は、ここで同じ問題を示す単純な例です:
0123ここで
#include <string>
void foo (int&,int){}
void foo (int&,float){}
template <typename T>
void foo (int&& a, T b) {
foo(a, b);
}
int main()
{
std::string s;
typedef decltype(foo(1,s)) foo_type;
}
Live Demo
は、関連する規格の引用符(N4140)は次のとおりです。
オーバーロードの解決が関与しているため、宣言はインスタンス化する必要があります。
[temp.inst]/10:
If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated (14.8.3).
のみ宣言ニーズインスタンス化する:
[temp.over]/5:
Only the signature of a function template specialization is needed to enter the specialization in a set of candidate functions. Therefore only the function template declaration is needed to resolve a call for which a template specialization is a candidate.
と実装は、関数本体をインスタンス化することはできません。
[temp.inst]/11:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation.
それは 'のstd :: declval <はstd :: ostreamに&>()'と正しく反応します。しかし、なぜ私は考えていない。 – Quentin