qhull / qhull

Qhull development for www.qhull.org -- Qhull 2020.2 (8.1-alpha1) at https://github.com/qhull/qhull/wiki
Other
716 stars 191 forks source link

libqhullcpp: template arguments in constructor declarations break C++20 compatibility #110

Closed elor closed 1 year ago

elor commented 2 years ago

Including libqhullcpp fails using g++ -std=c++20 due to extraneous template arguments <T> in some class constructor declarations, such as QhullSet<T>(const Qhull &q, setT *s) : QhullSetBase(q, s) { } in https://github.com/qhull/qhull/blob/master/src/libqhullcpp/QhullSet.h#L113-L123

Tested Compilers: gcc11.2.0 on CentOS7, Ubuntu 20.04, Windows 10 (via mingw), godbolt

Minimal example:

template <typename T>
class Foo {
    public:
    Foo<T>() { }
};

This fails with gcc-11 -std=c++20, but succeeds with gcc-11 -std=c++17 External godbolt: https://godbolt.org/z/4W8MYbYG7

Problem description: In the affected classes, constructors are declared with template arguments, e.g. QhullSet<T>(...) instead of QhullSet(...). Removing the template arguments <T> fixes the problem.

Question: Do the template arguments in the constructor serve any purpose in libqhullcpp, e.g. compatibility with legacy compilers?

Affected classes:

What does the current C++ standard say? Section 11.1.4* of the current C++ standard (c++20) states: in a member-declaration that belongs to the member-specification of a class or class template but is not a friend declaration (11.9.3), the id-expression is the injected-class-name (11.1) of the immediately-enclosing entity where the id_expression is what we consider "everything before the parenthesis" (barring [[attributes]]).

As I understand this, only the class name must be used in front of the constructor declaration's parentheses when declared inside the class definition. Thus, QhullSet<T>() is invalid, while QhullSet() is.

gcc 11 seems to follow this rule in c++20 mode, while the old rule ("it must be any entity-id") is used in c++17 mode.

Fortunately, clang and msvc are more forgiving.

* Section 11.1.5 in the latest draft

cbbarber commented 1 year ago

Thanks for your careful description. Legacy compilers should be OK. I checked C++ Primer 4th ed (2005). In Section 16.4 Class Template Members, unqualified names may be used inside the scope of a class template. Furthermore the elided type parameters were not used inside the corresponding definitions.

Merged #122