Saya tidak mengerti apa masalahnya: baik dalam kode saya atau di kompiler (kurang mungkin). Ada sepotong kode seperti ini:
#include <iostream>
#include <type_traits>
#include <set>
template<typename T, typename = void>
struct TestA: std::false_type {};
template<typename T>
struct TestA<T, std::void_t<typename T::reverse_iterator>> : std::true_type {};
template<typename T>
struct TestA<T, std::void_t<typename T::dummy_iterator>> : std::true_type {};
int main()
{
std::cout << TestA<std::set<int>>::value;
}
Baik GCC dan MSVC mengkompilasinya. Saya mengujinya di godbolt dengan versi GCC dan MSVC 17 (lokal) dan 19 yang berbeda. Berikut ini tautannya: https://godbolt.org/z/Enfm6L .
Tapi Dentang tidak mengkompilasi dan memancarkan kesalahan:
redefinition of `'TestA<T, std::void_t<typename T::dummy_iterator> >'`
Dan saya tertarik - mungkin ada beberapa bagian dari standar di mana kode ini tidak benar atau mungkin sesuatu yang lain.
Jawaban:
Ini sangat mungkin terkait dengan CWG 1558 .
Ini adalah cacat yang sejak ditangani, tetapi jika versi Dentang yang Anda gunakan belum mengimplementasikan perbaikan, masih mungkin menganggap kedua spesialisasi hanya dengan mendefinisikan argumen kedua sebagai
void
, dan tidak melakukan seluruh kesalahan penggantian substitusi. Solusinya adalah untuk tidak menggunakan alias polosstd::void_t
, melainkan versi yang sedikit lebih kompleksUntuk templat kelas (yang merupakan kepanjangan alias sekarang), kegagalan substitusi didefinisikan. Memasukkannya ke dalam contoh Anda akan membuat Dentang https://godbolt.org/z/VnkwsM .
sumber
enable_if
denganstd::disjunction
(atau membutuhkan klausa)