If you have a templated struct like
struct Base(T) {}
and you create an alias of that
alias Base Alias;
Then using the alias as an argument will confuse IFTI:
void foo(T)(Alias!(T) x) { }
Alias!(float) b;
Alias!(float) a;
foo(b); // IFTI fails
foo(a); // IFTI fails
foo!(float)(b) // ok
foo!(float)(a) // ok
IFTI works fine for both if Base!(T) is used as the function argument.
Why would you want to do this? I'm trying to port some C++ code. This code uses a lot of trivial struct inheritance to create a related set of value types (basically iterator types). They all derive from one struct Base(T), and the derived things don't actually add anything new. The derivation is used only to get a distinct type with a common ancestor. So I'm trying to at least preserve the type structure in anticipation of the day when D gets a better way to do this.
Comment #1 by wbaxter — 2007-08-29T20:41:56Z
Created attachment 173
Test program
Comment #2 by burton-radons — 2008-01-29T16:34:13Z
Here's a simpler example showing what appears to be the same problem:
template A (T)
{
alias T A;
}
void func (T) (A! (T) a)
{
}
void main ()
{
func (4);
}
This fails compilation in DMD 1.026 with:
template d.array.func(T) does not match any template declaration
template d.array.func(T) cannot deduce template function from argument types (int)
There is no workaround, this is bad!
Comment #3 by bugzilla — 2008-02-21T00:59:49Z
Consider the following more general case:
template A(T) { alias R A; }
void func(T)(A!(T).R a) { }
void main() { func (4); }
So the call tells you that A!(T).R should be int. You need to (1) find the set of Ts that satisfy the condition, and (2) prove that that set is { int }. I'm not sure this is tractable, and even if it were, there's a bit too much AI involved to make this a practical language feature.
(Thanks to Andrei for helping me with this)
C++ is not capable of doing this, either. Here's an example:
template<class T> struct Bar
{
typedef T a;
};
template<class T> void foo(Bar<T>::A a) { }
void main()
{
foo(3);
}
Comment #4 by bugzilla — 2008-02-21T01:03:46Z
*** Bug 1848 has been marked as a duplicate of this bug. ***
Comment #5 by bugzilla — 2008-02-21T01:05:01Z
*** Bug 1661 has been marked as a duplicate of this bug. ***
Comment #6 by wbaxter — 2008-02-21T02:52:31Z
I think maybe Burton, in trying to help, has confused the issue here.
All my initial report was saying is that if you use an alias of a template type instead of the original type, then IFTI stops working.
Here's the example again:
This *works*:
struct Base(T) {}
void foo(T)(Base!(T) x) {}
main() {
Base!(float) b;
foo(b); OK
}
But just by making an alias of the Base type, it no longer works:
struct Base(T) {}
alias Base Alias;
void foo(T)(Alias!(T) x) {}
main() {
Base!(float) b;
foo(b); // fails!
}
Alias is supposed to be the exact same type as Base, but yet template matching fails when that's the parameter.
I think this is a different issue from the one Burton tacked on, and from the one you said was invalid.
Comment #7 by bugzilla — 2008-02-22T16:18:59Z
You're right, that is a different issue. I'll fix it.