Для меня это выглядит как ошибка компилятора: вам действительно нужны побочные эффекты от T{}
? Вся конструкция decltype((void)T{})
должна отбрасывать инициализированный нулями T
, что позволяет получить неоцененные побочные эффекты - так какой смысл в таком побочном эффекте, если он есть?
Если вы упростите его, просто используя void
или даже пропустив весь второй тип, проблема сразу исчезнет ( живая демонстрация на wandbox ):
template<typename T, typename U = void>
struct Test
{
static const int value = 0;
};
template<typename T>
struct Test<T, void>
{
static const int value = 2;
};
template<typename T>
struct Test<T*, void>
{
static const int value = 1;
};
int main(){
std::cout << Test<int*>::value << "\n";
return 0;
}
Может быть, есть некоторые сложные детали, которые я пропустил, но я пробовал много вариантов, включая комбинации std::declval
, std::result_of
, шаблоны псевдонимов, typedefs, ни одна из которых не дала мне ничего значимого.
Но если мы переместим часть decltype((void)T{})
:
template<typename T>
using wrap = decltype((void)T{});
template<typename T>
struct Test<T, wrap<T>>
{
static const int value = 2;
};
template<typename T>
struct Test<T*, wrap<T>>
{
static const int value = 1;
};
GCC кричит: ambiguous template instantiation for 'struct Test<int*, void>'
. Что для меня является признаком того, что что-то идет не в том направлении.