我使用G ++ 6.1.0(-std=c++14
switch)遇到以下問題,我不明白編譯器爲什麼拒絕代碼。在SFINAE上下文中作爲模板模板參數傳遞的引用類型的別名模板
我有一個輔助結構is_well_formed
代替另一種類型的供應到它時檢查,如果提供的模板模板參數很好地形成:
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 {};
我要檢查一個類型是否可引用。所以我的想法是寫:
// (#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!?");
這三個別名之間有什麼區別?void_t<T&>
解決方案最優雅嗎?或者是否可以修改is_well_formed
幫助器結構以支持第一個reference
版本?
編輯:我測試了MSVC「15」預覽版4和(#1)
和(#3)
包括斷言的代碼。但是,當我嘗試(#2)
時,無效參考斷言不起作用,即在替換過程中信息丟失,並且永遠不會選擇過載。哪個編譯器是正確的?
is_well_formed
幫助程序對應於can_apply
結構體,它曾經在SFINAE上的Stack Overflow文檔頁面中記錄,我剛剛刪除了參數包。完整的示例代碼:
#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