Call to is ambiguous nur für Clang
-
Hallo,
ich habe folgendes in meinem Header:
/** * Returns true, if lhs is smaller than rhs by more than tolerance. */ template<typename Type> typename utils::EnableIf<(not IsVector<Type>::value), bool >::Type smaller ( Type lhs, Type rhs, Type tolerance = NUMERICAL_ZERO_DIFFERENCE); /** * Returns true, if lhs is equals or smaller than rhs by more than tolerance. */ template<typename Type> typename utils::EnableIf<(not IsVector<Type>::value), bool >::Type smallerEquals ( Type lhs, Type rhs, Type tolerance = NUMERICAL_ZERO_DIFFERENCE);in dazugehöriger Definition:
template<typename Type> inline typename utils::EnableIf<(not IsVector<Type>::value), bool >::Type smaller ( Type lhs, Type rhs, Type tolerance ) { return lhs - rhs < -tolerance; } template<typename Type> inline typename utils::EnableIf<not IsVector<Type>::value, bool >::Type smallerEquals ( Type lhs, Type rhs, Type tolerance ) { return lhs - rhs <= tolerance; }das ganze wird nun getestet:
validate (smaller(a, b, eps)); validate (smallerEquals(a, b, eps));Der ganze Code kompiliert problemlos mit gcc 4.9.1. Wenn ich nun probiere es mit clang++ 3.4.2 zu kompilieren, meldet smallerEquals (und nur smallerEquals!) einen Fehler:
clang++ -o build/debug/tarch/la/tests/ScalarTest.o -c -fPIC -g3 -O0 -DDebug -DAsserts -Isrc -Isrc -I/usr/include/openmpi -I/usr/include -I/usr/include/python2.7 -I/usr/include/python2.7/numpy src/tarch/la/tests/ScalarTest.cpp src/tarch/la/tests/ScalarTest.cpp:53:13: error: call to 'smallerEquals' is ambiguous validate (smallerEquals(a, b, eps)); ^~~~~~~~~~~~~ src/tarch/tests/TestMacros.h:45:37: note: expanded from macro 'validate' #define validate(booleanExpr) if (!(booleanExpr)) { \ ^ src/tarch/la/ScalarOperations.h:77:13: note: candidate function [with Type = double] >::Type smallerEquals ( ^ src/tarch/la/ScalarOperations.cpph:79:9: note: candidate function [with Type = double] >::Type smallerEquals ( ^ 1 error generated.Mir ist vor allem vollständig unverständlich, weshalb smaller keinen Fehler produziert, smallerEquals jedoch schon. Und das wiederrum nur mit clang, nicht mit gcc. Eben habe ich nochmal im Verzeichniss gegrept, smaller / smallerEquals kommt nur an den obigen Stellen vor.
Ich habe auch schon mal versucht smaller und smallerEquals zu vertauschen (sowohl im Aufruf als auch in Definition/Deklaration), aber der Fehler bleibt bei smallerEquals.
Wer kann mir Tipps geben, wo da das Problem sein könnte? Sollten noch Infos fehlen, liefere ich gerne alles nach!
Vielen Dank und Grüße,
Florian
-
Clang nimmt wohl fälschlicherweise an, dass du zwei verschiedene Funktionstemplates deklarierst; dabei wird es sich um einen Bug handeln.
P.S.:
Warum verwendest du nichtstd::enable_if? Kompilierst du etwa für C++03?
-
Clang beißt sich an den Klammern um den Ausdruck im Template-Argument an
enable_iffest
#include <type_traits> auto const NUMERICAL_ZERO_DIFFERENCE = 351; template<typename Type> typename std::enable_if<( not std::is_integral<Type>::value ), bool>::type /// Entferne hier die Klammern, dann kompiliert es /// ^ ^ smallerEquals ( Type lhs, Type rhs, Type tolerance = NUMERICAL_ZERO_DIFFERENCE ); template<typename Type> inline typename std::enable_if<not std::is_integral<Type>::value, bool>::type smallerEquals( Type lhs, Type rhs, Type tolerance ) { return lhs - rhs <= tolerance; } int main() { float a{}, b{}, eps{}; smallerEquals( a, b, eps ); }
-
Hallo!
Danke für den Code und den Tipp mit den Klammern. Probiere es morgen dann mal aus.
Ich kompiliere nicht nur für C++03, sondern sogar für C++98, also das was GNU und Clang ohne Optionen als Standard benutzen. Ich hoffe, dass das Projekt irgendwann auf C++11 umgestellt werden kann. Leider kommt es auch auf sehr großen HPC Systemen zum Einsatz und da sind die Compiler häufig etwas angestaubt.
Viele Grüße!
EDIT: Vielen Dank nochmal, jetzt läuft es und kompiliert mit clang.
-
Arcoth schrieb:
Clang beißt sich an den Klammern um den Ausdruck im Template-Argument an
enable_iffest
und hat damit recht. Und gcc hat auch recht, das Programm ist ill-formed, muss aber nicht diagnostiziert werden (14.5.6.1/6). U.a. Die Templateargumentliste zwischen verschiedenen Deklarationen des gleichen Templates muss Token für Token identisch sein, ausser dass andere Templateparameternamen verwendet werden dürfen, und diese in der Argumentlist entsprechend substituiert werden. Klammern schliesst das leider nicht ein.