以下のコードは、Visual Studio 2013、gcc 4.8、clang 3.4、および clang 3.5 (Apple LLVM 6.0) でコンパイルされますが、clang 3.6 (Apple LLVM 6.1 経由) ではコンパイルされません。
このコードは、コードベースの複雑なクラスの簡略化されたバージョンであり、問題を示すために最低限必要なものです。
問題の核心は、 ;を受け入れるコンストラクターが存在するためTYPED_VALUE
、3.6 では、のコピー構築がテンプレート化された型の変換演算子を評価することです。これによりが評価され、 の定義が必要になります(ここでは提供できません - 完全なコードでは循環依存が発生します)。STRING
STRING
std::is_constructible
STRING
class STRING;
class TYPED_VALUE
{
public:
TYPED_VALUE( const TYPED_VALUE& ) = default; // explicit or implicit doesn't make a difference
TYPED_VALUE( const STRING & ) {}
template< typename TYPE, typename std::enable_if<!std::is_pointer< TYPE >::value && !std::is_constructible< TYPE, const STRING& >::value && !std::is_constructible< TYPE, bool >::value, int >::type = 0 >
operator TYPE( void ) const = delete;
};
class TYPED_STORAGE
{
public:
TYPED_STORAGE( const TYPED_VALUE &v ) : value( v ) {}
TYPED_VALUE value;
};
エラーメッセージは
/type_traits:2329:38: error: incomplete type 'SICORE::STRING' used in type trait expression
: public integral_constant<bool, __is_constructible(_Tp, _Args...)>
^
/main.cpp:348:99: note: in instantiation of template class 'std::__1::is_constructible<SICORE::STRING, const SICORE::STRING &>' requested here
template< typename TYPE, typename std::enable_if<!std::is_pointer< TYPE >::value && !std::is_constructible< TYPE, const STRING& >::value && !std::is_constructible< TYPE, bool >::value, int >::type = 0 >
^
/main.cpp:349:9: note: while substituting prior template arguments into non-type template parameter [with TYPE = SICORE::STRING]
operator TYPE( void ) const = delete;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
/main.cpp:355:56: note: while substituting deduced template arguments into function template 'operator type-parameter-0-0' [with TYPE = SICORE::STRING, $1 = (no value)]
TYPED_STORAGE( const TYPED_VALUE &v ) : value( v ) {}
^
/main.cpp:340:11: note: forward declaration of 'SICORE::STRING'
class STRING;
^
私には、これは 3.6 のバグのように思えます。以前のバージョンでは、オーバーロードの解決により、テンプレート引数を評価することなく、コピー コンストラクターが最適であると判断されました。私にもっと;)
(これは、コンストラクターまたは変換演算子のいずれかを明示的にすることで修正できますが、それは私たちが望む動作ではありません)
答えを知っている標準的な専門家はいますか?