G ++ 6.1.0 (-std=c++14
anahtarı) ile ilgili bir sorunla karşılaştım ve derleyicinin kodu neden reddettiğini anlamıyorum.Başvuru türü için Alias şablonu şablon şablonu argümanı olarak SFINAE bağlamında iletildi
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 {};
Bir tür referans verilebilir olup olmadığını kontrol etmek istiyorum:
Ben verilen şablon şablon argümanı biçimi doğruysa içine başka verilen türünü değiştirirken kontrol eden bir yardımcı yapı is_well_formed
var. Yani benim fikrim şu yazmaktı:
// (#1)
template<class T>
using reference_t = T&;
static_assert(!is_well_formed<reference_t, void>::value, "Reference to void!?");
Ama derleyici hatası alıyorum: Ayrıca aşağıdaki
// (#2)
template<class T>
using reference_t = void_t<T&>;
: Aynı static_assert
ile Alternatif aşağıdaki işler
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'
Beni gerçekten yapan bulmacalar:
// (#3)
template<class T>
using pointer_t = T*;
static_assert(is_well_formed<pointer_t, void>::value, "No pointer to void!?");
Üç takma ad arasındaki fark nedir?void_t<T&>
çözümü en zarif olanı mı? Veya ilk reference
sürümünü desteklemek için is_well_formed
yardımcı yapısını değiştirmek mümkün mü?
DÜZENLEME
: Ben msvc "15" Önizleme 4 ve(#1)
ve iddia dahil
(#3)
çalışma ile kod test etti. Ancak,
(#2)
'u denediğimde, geçersiz referansın iddiası çalışmaz, yani, ikame sırasında bilgi kaybolur ve
false_type
aşırı yüklenme asla seçilmez. Hangi derleyici doğru?
is_well_formed
yardımcı kez SFINAE üzerinde yığın taşması dokümantasyon sayfasından belgelendi gelen can_apply
yapı tekabül, sadece parametre paketlerini kaldırıldı. Tam örnek kod:
#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;
}
İlginç. Bu, yalnızca 'reference_t' bir referans tipi sağladığında başarısız olur. –
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77575 –
@ T.C olarak rapor edildi. Eh, bu hızlıydı.: D Bu gerçekten bir böcek ve kimse daha önce karşılaştığı/bildirdiği için gerçekten garip - bu en egzotik kod gibi görünmüyor ... – w1th0utnam3