G ++ 6.1.0(-std=c++14
スイッチ)で次の問題が発生しましたが、コンパイラがコードを拒否する理由がわかりません。SFINAEコンテキストでテンプレートテンプレート引数として渡される参照型のエイリアステンプレート
template<template<typename> typename R, typename T, typename = void>
struct is_well_formed : std::false_type {};
template<template<typename> typename R, typename T>
struct is_well_formed<R, T, void_t<R<T>>> : std::true_type {};
私はタイプが参照可能であるかどうかを確認したい:
私は付属のテンプレートテンプレート引数がうまく形成されている場合、その中に別の供給タイプに置き換えたときにチェックするヘルパー構造体is_well_formed
を持っています。
// (#1)
template<class T>
using reference_t = T&;
static_assert(!is_well_formed<reference_t, void>::value, "Reference to void!?");
しかし、私は、コンパイラのエラーを取得:だから私のアイデアは、次のように記述することでした
main.cpp: In instantiation of 'struct is_well_formed<reference_t, double>':
main.cpp:62:51: required from here
main.cpp:54:20: error: type/value mismatch at argument 1 in template parameter list for 'template<template<class> class R, class T, class> struct is_well_formed'
: std::false_type {};
^
main.cpp:54:20: note: expected a class template, got 'reference_t'
main.cpp:54:20: error: type/value mismatch at argument 1 in template parameter list for 'is_well_formed<R, T, <template-parameter-1-3> >::is_well_formed'
main.cpp:54:20: note: expected a class template, got 'reference_t'
同じstatic_assert
を持つ代わりに、次の作品:
// (#2)
template<class T>
using reference_t = void_t<T&>;
さらに、以下の作品は本当に私を困惑させる:
// (#3)
template<class T>
using pointer_t = T*;
static_assert(is_well_formed<pointer_t, void>::value, "No pointer to void!?");
3つのエイリアスの違いは何ですか?void_t<T&>
の解決策はありますか?または、reference
バージョンをサポートするようにis_well_formed
ヘルパー構造を変更することはできますか?
EDIT:私はMSVC "15" のプレビュー4、およびアサートを含む(#1)
と(#3)
仕事でコードをテストしました。しかし、私が試してみると(#2)
void参照のアサートが機能しません。つまり、置換中に情報が失われ、false_type
オーバーロードが選択されません。どのコンパイラが正しいのですか?
is_well_formed
ヘルパーはcan_apply
構造体に対応しています。これは、Stack Overflowのドキュメントページ(SFINAE)に記載されていましたが、パラメータパックを削除しました。完全なサンプルコード:
#include <utility>
// Only defined in std for C++17
template <class...>
using void_t = void;
// (#1) Compiler error during substitution in is_well_formed
template<class T>
using reference_t = T&;
// (#2) Ok, asserts work
/*
template<class T>
using reference_t = void_t<T&>;
*/
// (#3) Ok, asserts work
template<class T>
using pointer_t = T*;
template<template<typename> typename R, typename T, typename = void>
struct is_well_formed
: std::false_type {};
template<template<typename> typename R, typename T>
struct is_well_formed<R, T, void_t<R<T>>>
: std::true_type {};
int main(int, char**)
{
static_assert(is_well_formed<reference_t, double>::value, "No reference to double!?");
static_assert(!is_well_formed<reference_t, void>::value, "Reference to void!?");
static_assert(is_well_formed<pointer_t, double>::value, "No pointer to double!?");
static_assert(is_well_formed<pointer_t, void>::value, "No pointer to void!?");
return 0;
}
興味深い。これは 'reference_t'が参照型を生成する場合にのみ失敗するようです。 –
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77575 –
@ T.Cとして報告されています。まあ、それは速かった。:Dこれは実際にはバグで誰も遭遇していない/それ以前に報告した場合は本当に変です - これは最もエキゾチックなコードのようには見えません... – w1th0utnam3