Thread overview
std.algorithm.cmp is conflicting with itself.
Aug 11, 2022
realhet
Aug 11, 2022
Paul Backus
Aug 11, 2022
realhet
Aug 11, 2022
bachmeier
Aug 11, 2022
realhet
Aug 12, 2022
bachmeier
Aug 12, 2022
realhet
August 11, 2022

Hello,

I try to make an overload group of cmp() functions in my utility module but everything works well except when I import some 3rd party module that imports std.algorithm. Then I get an error:
C:\D\testCmpOverload.d(11,8): Error:
function std.algorithm.comparison.cmp!(string, string).cmp at
c:\D\ldc2\bin..\import\std\algorithm\comparison.d(625,6)
conflicts with
function std.algorithm.comparison.cmp!(string, string).cmp at c:\D\ldc2\bin..\import\std\algorithm\comparison.d(625,6)

It is conflicting with itself.
My question is that how to solve this without choosing a different identifier, other than 'cmp'?

Here's the utility module:

module testcmpmodule;

//publicly output these modules, like I did in my always used 'utils' module.
public import std.algorithm, std.math, std.stdio;

import std.range, std.traits;

//create function overload group
public import std.algorithm : cmp;
public import std.math      : cmp;

auto cmp(A, B)(in A a, in B b)
if(!(isInputRange!A && isInputRange!B)          //exclude std.algorithm.cmp
&& !(isFloatingPoint!A && isFloatingPoint!B))   //exclude std.math.cmp
{
  return a==b ? 0 : a<b ? -1 : 1; //last resort
}

The other module that publishes the utility module:

module testcmpmodule2;

public import std.algorithm, testcmpmodule, std.stdio;

void w(A...)(in A a){ writeln(a); }

The main module:

import testcmpmodule2;

void main(){
  w(cmp(.1, .2));   //std.math.cmp
  w(cmp("a", "b")); //std.algorithm.cmp   <- here's the error
  w(cmp(1, 2));     //my cmp
}

I have a project with 40K lines. And I don't even have to use public import in the 'second' module, like in this example, the error is happenning because something pulls it in.

My not so good solution was this:

alias cmp_ = cmp; //so wherever there is a conflict, I only have to put a _ symbol after the cmp, but that's still ugly.


To be more precise:
I have a het.math module where I implement math routines that are close to opengl.
That module does a log of patching of various std functions, mainly enable them to work on vector/matrix.
I also have a het.utils module which publicly imports het.math, and also many std modules.
And finally when I make an application using the complete framework, I lost the game finding what imports std.algorithm and thus ruining my fragile function overload groups.

Also I wonder why there is no cmp() function for integers in the std library?  It's easy to code (a-b   or   a==b?0:a<b?-1:1)  but still, I can do mistakes. (And I did: many of my comparisons had bugs :D So I wan't to centralize cmp())


Thank You in advance!

August 11, 2022

On Thursday, 11 August 2022 at 17:46:00 UTC, realhet wrote:

>

Here's the utility module:

module testcmpmodule;

//publicly output these modules, like I did in my always used 'utils' module.
public import std.algorithm, std.math, std.stdio;

import std.range, std.traits;

//create function overload group
public import std.algorithm : cmp;
public import std.math      : cmp;

auto cmp(A, B)(in A a, in B b)
if(!(isInputRange!A && isInputRange!B)          //exclude std.algorithm.cmp
&& !(isFloatingPoint!A && isFloatingPoint!B))   //exclude std.math.cmp
{
  return a==b ? 0 : a<b ? -1 : 1; //last resort
}

The other module that publishes the utility module:

module testcmpmodule2;

public import std.algorithm, testcmpmodule, std.stdio;

void w(A...)(in A a){ writeln(a); }

What's happening here is that the overload set created by the utility module is conflicting with the overload set created by the public import in testcmpmodule2. If you remove std.algorithm from testcmpmodule2's public import line, the code compiles successfully.

August 11, 2022

On Thursday, 11 August 2022 at 18:10:31 UTC, Paul Backus wrote:

>

... If you remove std.algorithm from testcmpmodule2's public import line, the code compiles successfully.

Yes, but in the 40 module project I'm unable to make it work.
I doublechecked that the only public import of std.algorithm is in that utility module which is making the overload set.
If a third party module uses std.algorithm, it's not public, and I also restrict the import for specific names that it uses.
And still I'm not able to cmp("a", "b"), because of the conflict.

What I'm thinking of maybe it is some module in the std library that can make a second conflicting overload set? (I public import some std modules, and if there is a public import inside that module to std.algorithm it can happen. I guess it's a possibility.)

August 11, 2022

On Thursday, 11 August 2022 at 18:32:54 UTC, realhet wrote:

>

On Thursday, 11 August 2022 at 18:10:31 UTC, Paul Backus wrote:

>

... If you remove std.algorithm from testcmpmodule2's public import line, the code compiles successfully.

Yes, but in the 40 module project I'm unable to make it work.
I doublechecked that the only public import of std.algorithm is in that utility module which is making the overload set.
If a third party module uses std.algorithm, it's not public, and I also restrict the import for specific names that it uses.
And still I'm not able to cmp("a", "b"), because of the conflict.

What I'm thinking of maybe it is some module in the std library that can make a second conflicting overload set? (I public import some std modules, and if there is a public import inside that module to std.algorithm it can happen. I guess it's a possibility.)

std.string does a public import of std.algorithm.cmp.

August 11, 2022

On Thursday, 11 August 2022 at 19:33:31 UTC, bachmeier wrote:

>

std.string does a public import of std.algorithm.cmp.

That was it! Thanks!

Conclusion: This is how to overload cmp()


//this is the only place from where all other modules can see these std modules
public import std.string, std.uni, std.algorithm, std.math;

import std.range, std.traits;

//create function overload group
public import std.algorithm : cmp;
public import std.math      : cmp;

auto cmp(A, B)(in A a, in B b)                  //the custom cmp() function
if(!(isInputRange!A && isInputRange!B)          //exclude std.algorithm.cmp
&& !(isFloatingPoint!A && isFloatingPoint!B))   //exclude std.math.cmp
{
  return a==b ? 0 : a<b ? -1 : 1;
}
August 12, 2022

On Thursday, 11 August 2022 at 22:34:11 UTC, realhet wrote:

>

On Thursday, 11 August 2022 at 19:33:31 UTC, bachmeier wrote:

>

std.string does a public import of std.algorithm.cmp.

That was it! Thanks!

Conclusion: This is how to overload cmp()

A search of the forum suggests this is how I learned about it. I most likely had the same problem early in my D career. I don't know if anything further was ever done to fix the problem (if anything could be done), but if this is a design mistake that can't be fixed, there should at least be an informative error message so we know where to look. The error message you posted already identifies it as std.algorithm.comparison.cmp.

August 12, 2022

On Friday, 12 August 2022 at 02:13:48 UTC, bachmeier wrote:

>

Informative error message

I'm making something like an IDE.
The text search function in it is able to search across all user modules.
I thought about filtering the search results by context.
The following contexts are planned already:

  • inside code
  • inside comment
  • inside string literal

Now I can add:

  • inside import declarations
  • search inside std

That would help a lot with this type of error message.

I think extending some general std routines is really helpful.
This way I can write code in DLang, copy/paste it into GLSL and with minimal changes it can work there as well, and vice verse.

The only downside is that when I want to use 3rd party packages: I have to check and modify them to not harm my overload sets with their imports.