Почему замена типа члена `x` на` decltype (x) `в списке аргументов ctor нарушает вывод аргументов шаблона класса? - PullRequest
2 голосов
/ 04 ноября 2019

Я пытаюсь написать какое-то чудовище препроцессора, чтобы сделать простые ctors.

Это компилируется с g++ -std=c++17:

template<typename T>
struct foo{
    T x;
    foo(T _x):x(_x){}
};
auto x=foo(3);

Но монстру было бы труднознаю тип x, поэтому я попробовал это:

template<typename T>
struct foo{
    T x;
    foo(decltype(x) _x):x(_x){}
};
auto x=foo(3);

, что не удается (class template argument deduction failed). Но decltype(x) это просто T в любом случае, верно? Так почему же примеры кода не эквивалентны?

Ответы [ 2 ]

4 голосов
/ 04 ноября 2019

То, что вы написали - это круговая логика. Подумайте об этом так.

Компилятор видит foo(3). foo называет шаблон класса, поэтому он пытается выполнить вывод аргумента шаблона класса, чтобы выяснить, каким должен быть T в foo.

CTAD начинается с взятия всех конструкторов ипостроение шаблонов выводов из них. У вас есть один конструктор, поэтому руководство для него должно выглядеть следующим образом:

template<typename T> foo(decltype(foo<T>::x) _x) -> foo<T>;

Чтобы вывести параметр шаблона T для foo, вам необходимо создать экземпляр foo .. с T. Которого у вас еще нет , потому что выяснение, что такое T, - это то, почему вы создали это руководство по выводам.

1 голос
/ 04 ноября 2019

Короткий ответ здесь, потому что так говорит стандарт C ++. decltype выражения не могут быть выведены в качестве параметра шаблона.

17.8.2.5 Вывод аргументов шаблона из типа [temp.deduct.type]

Неведуемые контексты:

[...]

- Выражение спецификатора decltype.

Вы используете C ++ 17. Если вы используете decltype, чтобы скрыть какое-то чудовище, вам, вероятно, потребуется использовать руководства по выводам в C ++ 17, чтобы обойти это.

...