CMakePP / CMakePPLang

Object-oriented extension to the CMake language.
http://cmakepp.github.io/CMakePPLang/
Apache License 2.0
11 stars 4 forks source link

cpp_assert_signature does not work correctly with lists #3

Open ryanmrichard opened 4 years ago

ryanmrichard commented 4 years ago

cpp_assert_signature does not work correctly with lists.

Let's say you have a function:

function(my_fxn arg0 arg1 arg2)
    cpp_assert_signature("${ARGV}" bool int str)
endfunction()

and you call it like:

my_fxn(TRUE 1 "foo;bar")

In debug mode, you will get an error: "Function takes 3 argument(s), but 4 was/were provided". The problem is cpp_assert_signature sees that it should get three arguments, but it then sees that ARGV is a 4 element list. Without manually passing ARGV0, ARGV1, ...to maintain the partitioning, I'm not sure how to avoid this at the moment.

AutonomicPerfectionist commented 1 year ago

I think I found a possible solution using macros. It turns out, macros can loop over the argument lists of the functions in which they are called in if you use a very specific syntax, while still allowing to loop over their own arguments. The documentation on this behavior is here:

https://cmake.org/cmake/help/latest/command/macro.html#argument-caveats

Example:

macro(test_macro)
    # Hacky workaround to prevent the macro's ARGC from being inputted,
    # since only the literal ${ARGC} is replaced with the macro's count
    set(_tm_c "C")

    # CMake is weird and includes the stop, so we have to subtract one
    math(EXPR _tm_arg_count "${ARG${_tm_c}} - 1")

    foreach(arg RANGE ${_tm_arg_count})
        # Only exact ${ARGV0} etc is replaced with macro arguments
        # so this expression is left alone and evaluated according to the
        # calling function arguments
        message("Argument: ${ARGV${arg}}")
    endforeach()

    set(macro_args "${ARGV}")
    foreach(arg IN LISTS macro_args)
        message("Macro args: ${arg}")
    endforeach()

endmacro()

function(test_func)
    test_macro(1 2 "Hello")

endfunction()

set(l element1 element2)
test_func("${l}" "func1" "func2" 3 4)

Prints:

Argument: element1element2
Argument: func1
Argument: func2
Argument: 3
Argument: 4
Macro args: 1
Macro args: 2
Macro args: Hello