2

I'm trying to write some kind of preprocessor monstrosity to make simple ctors.

This compiles with g++ -std=c++17:

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

But it would be hard for the monstrosity to know the type of x, so I tried this:

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

Which fails (class template argument deduction failed). But decltype(x) is just T anyway, right? So why aren't the code samples equivalent?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
acupoftea
  • 181
  • 2
  • 11
  • This is [non deducible context](https://stackoverflow.com/questions/25245453/what-is-a-nondeduced-context); however since the canonical dupe doesn't explicitly explain that `decltype` introduces non-deducible context, this wouldn't qualify as a dupe, in my eyes. – Sam Varshavchik Nov 04 '19 at 02:20

2 Answers2

5

What you've written is kind of circular logic. Think of it like this.

The compiler sees foo(3). foo names a class template, so it attempts to perform class template argument deduction in order to figure out what the T in foo should be.

CTAD starts off by taking all of the constructors and building template deduction guides out of them. You have one constructor, so the guide for it would have to look like:

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

In order to deduce the template parameter T for foo, you would need to instantiate foo... with T. Which you don't have yet because figuring out what T is is why you built this deduction guide in the first place.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
1

The short answer here is because the C++ standard says so. decltype expressions cannot be deduced as a template parameter.

17.8.2.5 Deducing template arguments from a type [temp.deduct.type]

The non-deduced contexts are:

[...]

— The expression of a decltype-specifier.

You are using C++17. If you're using decltype to hide some monstrosity, you'll probably need to use C++17's deduction guides, to work around it.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148