I have been bashing my head in for the past 9 hours.
I just got a new MacBookPro with the M3 processor (ARM), and installed all command-line tools, including clang
, with xcode-select --install
.
clang++
is mistaking a friend
declaration within a class and its definition outside the class as two distinct functions, despite having identical signatures.
I have reduced my problematic code as much as humanly possible to expose the cause of the compilation errors. I am sure this means clang
is faulty, as I've been writing C++ for a while and have never run into this - the code also compiles fine on my other Macs and Linux instance.
I deleted and reinstalled all the command-line tools. Same stuff.
Here is the bare-bones code:
#include <iostream>
namespace gml {
template <typename T>
concept Numeric = requires (T value) {
T{};
// lots of stuff...
};
template <Numeric T>
class tensor {
// lots more stuff...
public:
tensor() = default; // constructs an empty tensor
template <Numeric U, Numeric V>
friend bool operator==(const tensor<U>&, const tensor<V>&);
};
template <Numeric U, Numeric V>
bool operator==(const tensor<U>& t1, const tensor<V>& t2) {
return true;
}
}
int main() {
gml::tensor<long double> t;
gml::tensor<long double> t3;
std::cout << std::boolalpha << "t == t3: " << (t == t3) << std::endl;
return 0;
}
... and here is the exact compilation error I get from the above:
test.cpp:26:54: error: use of overloaded operator '==' is ambiguous (with operand types 'gml::tensor<long double>' and 'gml::tensor<long double>')
std::cout << std::boolalpha << "t == t3: " << (t == t3) << std::endl;
~ ^ ~~
test.cpp:15:21: note: candidate function [with U = long double, V = long double]
friend bool operator==(const tensor<U>&, const tensor<V>&);
^
test.cpp:18:10: note: candidate function [with U = long double, V = long double]
bool operator==(const tensor<U> &t1, const tensor<V> &t2) {
^
1 error generated.
I would most appreciate it if someone could give me some insight on this.
P.S., I compiled using clang++ -std=c++20 test.cpp -o test
, and running clang++ --version
prints:
Apple clang version 15.0.0 (clang-1500.1.0.2.5)
Target: arm64-apple-darwin23.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
This seems to be a apple-clang bug and the program is well-formed. All three other compilers(gcc, clang and msvc) compiles the program just fine.
As a workaround for apple-clang, you can just define the friend template inside the class template:
namespace gml {
template <Numeric T>
class tensor {
public:
//other code as before
template <Numeric U, Numeric V>
friend bool operator==(const tensor<U>&, const tensor<V>&) //provide definition here inside class
{
return true;
}
};
}