Jump to page: 1 2
Thread overview
Why doesn't symbol wheelbarrowing work with function templates?
Jun 13, 2013
TommiT
Jun 13, 2013
Peter Alexander
Jun 13, 2013
Peter Alexander
Jun 13, 2013
TommiT
Jun 13, 2013
deadalnix
Jun 13, 2013
TommiT
Jun 13, 2013
TommiT
Jun 13, 2013
TommiT
Jun 14, 2013
Timon Gehr
Jun 15, 2013
TommiT
Jun 15, 2013
Timon Gehr
Jun 15, 2013
TommiT
Jun 17, 2013
Kenji Hara
Jun 17, 2013
TommiT
June 13, 2013
"symbol wheelbarrowing" = "making symbols in other module(s) local to the current module"
(described in TDPL at page 148)

The problem:
-----------

module a;

int foo(int)
{
    return 42;
}

int bar(T)(int)
{
    return 42;
}

-----------

module b;

int foo(char)
{
    return 3;
}

int bar(T)(char)
{
    return 3;
}

-----------

module main;

import std.stdio;

import a;
import b;

// Works for foo:
alias foo = a.foo;
alias foo = b.foo;

// ...but not for bar:
alias bar = a.bar;
alias bar = b.bar; // Error: [1]

void main()
{
    writeln(foo(int.init));  // 42
    writeln(foo(char.init)); // 3

    //writeln(bar!(int)(int.init));
    //writeln(bar!(char)(char.init));
}

1. alias main.bar conflicts with alias main.bar
June 13, 2013
On Thursday, 13 June 2013 at 09:53:54 UTC, TommiT wrote:
> 1. alias main.bar conflicts with alias main.bar

This is why: they conflict.

If it worked, what would you expect bar!string() return?
June 13, 2013
On Thursday, 13 June 2013 at 10:16:40 UTC, Peter Alexander wrote:
> On Thursday, 13 June 2013 at 09:53:54 UTC, TommiT wrote:
>> 1. alias main.bar conflicts with alias main.bar
>
> This is why: they conflict.
>
> If it worked, what would you expect bar!string() return?

Oops, that's a bad example: bar has a parameter.

Which bar would you expect this to alias:

alias bar!string barstring;
June 13, 2013
On Thursday, 13 June 2013 at 10:16:40 UTC, Peter Alexander wrote:
> On Thursday, 13 June 2013 at 09:53:54 UTC, TommiT wrote:
>> 1. alias main.bar conflicts with alias main.bar
>
> This is why: they conflict.
>
> If it worked, what would you expect bar!string() return?

both bar templates take a regular argument as well as a template argument, so bar!string() would be an error saying something like "no template 'bar' matches the function call". But if you'd call bar!string(int.init), then I'd expect it to return 42, and with bar!string(char.init), I'd expect 3.
June 13, 2013
On Thursday, 13 June 2013 at 10:19:17 UTC, Peter Alexander wrote:
> On Thursday, 13 June 2013 at 10:16:40 UTC, Peter Alexander wrote:
>> On Thursday, 13 June 2013 at 09:53:54 UTC, TommiT wrote:
>>> 1. alias main.bar conflicts with alias main.bar
>>
>> This is why: they conflict.
>>
>> If it worked, what would you expect bar!string() return?
>
> Oops, that's a bad example: bar has a parameter.
>
> Which bar would you expect this to alias:
>
> alias bar!string barstring;

I'd expect that to be some kind of compile time error about the ambiguity of bar!string, given that both 'a' and 'b' are imported.
June 13, 2013
Well, I guess wheelbarrowing works with templates similar to functions if the template arguments are specified:

Doesn't work:
------------
import a;
import b;

void main()
{
    // Ambiguity errors:
    writeln(bar!string(int.init));
    writeln(bar!string(char.init));
}

Works:
------
import a;
import b;

alias bar = a.bar!string;
alias bar = b.bar!string;

void main()
{
    writeln(bar(int.init));  // 43
    writeln(bar(char.init)); // 3
}

... but I just realized I'm not actually asking what I'm trying to ask here. So, let me rephrase my question:

Why is the following ambiguous?
-----------
module a;

int foo(T)() if (is(T == int))
{
    return 42;
}

-----------
module b;

int foo(T)() if (is(T == char))
{
    return 3;
}

-----------
module main;

import std.stdio;

import a;
import b;

void main()
{
    writeln(foo!int()); // Error: ambiguous template declaration
}
June 13, 2013
On Thursday, 13 June 2013 at 10:52:56 UTC, TommiT wrote:
> Why is the following ambiguous?
> -----------
> module a;
>
> int foo(T)() if (is(T == int))
> {
>     return 42;
> }
>
> -----------
> module b;
>
> int foo(T)() if (is(T == char))
> {
>     return 3;
> }
>
> -----------
> module main;
>
> import std.stdio;
>
> import a;
> import b;
>
> void main()
> {
>     writeln(foo!int()); // Error: ambiguous template declaration
> }

The corresponding code in C++ works nicely:
-------------------------------------------
// a.h

#include <type_traits>

template <typename T, typename std::enable_if<
    std::is_same<T, int>::value,
int>::type = 0>
int foo()
{
    return 42;
}

-------------------
// b.h

#include <type_traits>

template <typename T, typename std::enable_if<
    std::is_same<T, char>::value,
int>::type = 0>
int foo()
{
    return 3;
}

-------------------
// main.cpp

#include <iostream>

#include "a.h"
#include "b.h"

int main()
{
    std::cout << foo<int>()  << std::endl; // 42
    std::cout << foo<char>() << std::endl; // 3
    return 0;
}


I'm just wondering whether the fact that the above (quoted) code doesn't work in D is based on some fundamental difference in how D and C++ work, or if it's some kind of a defect in D which we could change and make the above D code work.
June 13, 2013
On Thursday, 13 June 2013 at 10:19:17 UTC, Peter Alexander wrote:
> On Thursday, 13 June 2013 at 10:16:40 UTC, Peter Alexander wrote:
>> On Thursday, 13 June 2013 at 09:53:54 UTC, TommiT wrote:
>>> 1. alias main.bar conflicts with alias main.bar
>>
>> This is why: they conflict.
>>
>> If it worked, what would you expect bar!string() return?
>
> Oops, that's a bad example: bar has a parameter.
>
> Which bar would you expect this to alias:
>
> alias bar!string barstring;

It is ambiguous and you get an error.
June 14, 2013
On 06/13/2013 11:53 AM, TommiT wrote:
> "symbol wheelbarrowing" = "making symbols in other module(s) local to
> the current module"
> (described in TDPL at page 148)
>
> The problem:
> -----------
>
> ...
>
> 1. alias main.bar conflicts with alias main.bar

Compiler bug.

June 15, 2013
On Friday, 14 June 2013 at 05:36:32 UTC, Timon Gehr wrote:
> On 06/13/2013 11:53 AM, TommiT wrote:
>> "symbol wheelbarrowing" = "making symbols in other module(s) local to
>> the current module"
>> (described in TDPL at page 148)
>>
>> The problem:
>> -----------
>>
>> ...
>>
>> 1. alias main.bar conflicts with alias main.bar
>
> Compiler bug.

Would you also go as far as to say that you'd expect the following to be perfectly valid D code?

---------
module a;

void foo(T : int)() { }

---------
module b;

void foo(T : string)() { }

---------
module main;

import std.stdio;

import a;
import b;

alias foo = a.foo;
alias foo = b.foo; // [1]

void main()
{
    foo!int();
    foo!string();
}

---------
1) Error: alias main.foo conflicts with alias main.foo
« First   ‹ Prev
1 2