Я сталкиваюсь с неожиданными результатами при использовании псевдонимов шаблонов в качестве аргументов классов шаблонов, объявляющих частичные специализации. В некоторых случаях я даже заметил, что GCC 8.2 и Clang 6.0.0 не согласны с результатами. Код, иллюстрирующий мои случаи, можно найти ниже.
// A template struct named Foo.
template<typename>
struct Foo {};
// A template alias for type Foo.
template<typename TYPE>
using AliasFoo = Foo<TYPE>;
// A variadic template alias for type Foo.
template<typename... ARGS>
using VariadicAliasFoo = Foo<ARGS...>;
// A template struct named Bar.
template<template<typename...> class TEMPLATE, typename TYPE>
struct Bar
{
static constexpr bool value = false;
};
// Partial specialization of template struct Bar.
template<template<typename...> class TEMPLATE, typename... ARGS>
struct Bar< TEMPLATE, TEMPLATE<ARGS...> >
{
static constexpr bool value = true;
};
// The main function.
int main()
{
// These compile time assertions are satisfied (as expected).
static_assert(Bar<Foo, Foo<int> >::value, "");
static_assert(Bar<Foo, AliasFoo<int> >::value, "");
static_assert(Bar<Foo, VariadicAliasFoo<int> >::value, "");
// These compile time assertions fails with Clang 6.0.0 but succeed with GCC 8.2
static_assert(Bar<AliasFoo, Foo<int> >::value, "");
static_assert(Bar<AliasFoo, AliasFoo<int> >::value, "");
static_assert(Bar<AliasFoo, VariadicAliasFoo<int> >::value, "");
// These compile time assertions fails with Clang 6.0.0 and GCC 8.2.
static_assert(Bar<VariadicAliasFoo, Foo<int> >::value, "");
static_assert(Bar<VariadicAliasFoo, AliasFoo<int> >::value, "");
static_assert(Bar<VariadicAliasFoo, VariadicAliasFoo<int> >::value, "");
// Always return zero.
return 0;
}
Мой вопрос следующий: в соответствии со стандартом (C++ 17), каким должен быть результат последних шести утверждений времени компиляции в приведенном выше коде?
GCC реализует CWG 1286. Clang - нет.
Обратите внимание, что вам не нужно указывать второй аргумент для
static_assert
, начиная с C++ 17. Такжеreturn 0;
лишний. Более того, вы можете рассмотреть возможность наследованияBar
отstd::false_type
иstd::true_type
.