Skip to content

[BUG] CPP2_UFCS macros don't work with template functions/methods with multiple template arguments #82

@filipsajdak

Description

@filipsajdak

CPP2_UFCS macro is based on variadic macros. That means that every comma , in the macro separates two arguments for the macro (unless surrounded by parentheses ().

That makes below the cpp2 code (mixed mode):

#include <string>

template <auto from, auto to>
auto substr(const std::string& input) -> std::string {
    return input.substr(from, to-from);
}

main: () -> int = {
    test_string: std::string = "Unfortunatelly macros have limitations";
    cmd.substr<3,6>();
}

compiles to (skipping boilerplate):

[[nodiscard]] auto main() -> int{
    std::string test_string { "Unfortunatelly macros have limitations" }; 
    CPP2_UFCS_0(substr<3,6>, test_string);
}

And a call to CPP2_UFCS_0 will be perceived by the compiler as CPP2_UFCS_0((substr<3),(6>), (test_string)); (parentheses added to emphasize the problem. That will not compile and will end up with an error:

clang++ -std=c++20 -Iinclude ../tests/ufcs-method-limitations.cpp 
tests/ufcs-method-limitations.cpp2:10:30: error: too many arguments provided to function-like macro invocation
    CPP2_UFCS_0(substr<3,6>, test_string);
                             ^
include/cpp2util.h:487:9: note: macro 'CPP2_UFCS_0' defined here
#define CPP2_UFCS_0(FUNCNAME,PARAM1) \
        ^
tests/ufcs-method-limitations.cpp2:10:5: error: use of undeclared identifier 'CPP2_UFCS_0'
    CPP2_UFCS_0(substr<3,6>, test_string);
    ^
2 errors generated.

A similar error will happen for CPP2_UFCS version - that reminds me why we hate macros so much.

Normally, in such cases, we would add parentheses to give hints to the preprocessor where are the arguments. In this case when we do it we will look like:

CPP2_UFCS_0((substr<3,6>), test_string);

But it will also fail to compile with the error: expected unqualified-id:

clang++ -std=c++20 -Iinclude ../tests/ufcs-method-limitations.cpp 
tests/ufcs-method-limitations.cpp2:10:17: error: expected unqualified-id
    CPP2_UFCS_0((substr<3,6>), test_string);
                ^
tests/ufcs-method-limitations.cpp2:10:17: error: expected unqualified-id
error: constexpr if condition is not a constant expression
tests/ufcs-method-limitations.cpp2:10:5: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<std::string &>' requested here
    CPP2_UFCS_0((substr<3,6>), test_string);
    ^
include/cpp2util.h:494:2: note: expanded from macro 'CPP2_UFCS_0'
}(PARAM1)
 ^
3 errors generated.

Unless there is a trick to make that macro work again we will need to come up with some other idea to solve it.

I found that bug while trying to update the function call chaining PR (#18). Probably working UFCS will not be possible without semantic analysis on cppfront side.

The same will be needed to allow Unified "." member/scope selection (e.g., std.swap(x,y)) - it is impossible to distinguish if std is a namespace by using require expressions or decltype hacks (already tried that).

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions