Thursday, October 17, 2024

Why is not C++ Lambdas and IOS Blocks Absolutely Associative?

I’m new to IOS programming, and am studying about blocks and lambdas. In my analysis on blocks and c++ lambdas I learn that primarily lambdas can change blocks as a result of they will do just about the identical factor. This seems to be case aside from the seize clause and the C++ particular (mutable and throw) optionally available key phrases. I’ve discovered some variations which may make a distinction – however unsure. I can create a std::perform wrapper sort variable (lambda) and assign a block and its equal lambda assertion(s). Nevertheless, if I create a block sort variable and try to assign a lambda to it – the compile terminates with an error. Why? I am going to present the code and the error output beneath. Additionally, I can not typedef a lambda, I have to use a std::perform wrapper perform sort to do the equal. Why?


#embrace <iostream>
#embrace <purposeful>
#embrace <pthread.h>
#embrace <xpc/xpc.h>
#embrace <dispatch/dispatch.h>

#outline SHOW_COMPILE_ERROR
// add feedback on subsequent line to see the compile error
#undef SHOW_COMPILE_ERROR


// You can't create a lambda typedef, however you possibly can create a basic function
// polymorphic perform wrapper from std::wrapper
// e.g. typedef  [] (xpc_object_t) -> void do_custom_message_l_t; isn't authorized
// however the std::perform declaration is authorized - why?
typedef std::perform<void(xpc_object_t)> do_custom_msg_l_t;
// block typedefs are authorized as beneath
typedef void (^do_custom_msg_b_t)(xpc_object_t);

// create a perform declaration with a callback utilizing both
// approaches - the block typedef or the std::perform wrapper
// simply as nicely
xpc_object_t build_message(int func,
                           do_custom_msg_b_t&);
xpc_object_t build_message(int func,
                           do_custom_msg_l_t&);

// create a few world variables of the block or std::perform sort
do_custom_msg_b_t do_custom_msg_b;
do_custom_msg_l_t do_custom_msg_l, do_custom_msg_l2;

#if outlined(SHOW_COMPILE_ERROR)
do_custom_msg_b_t do_custom_msg_b2;
#endif

int principal(int argc, char *argv[])
{
    // assign a block to the block sort world
    do_custom_msg_b = ^(xpc_object_t custom_message) {
        auto p= xpc_copy_description(custom_message);
        std::cerr << "Customized Message Objects: " << p << std::endl;
        free(p);
    };

    // assign a std::perform sort a lambda definition - cool.
    // however change the variable to do_custom_msg_b and all of a sudden there
    // is an error!  So you possibly can assign a lambda definition to a block
    // variable sort.  Very bizarre.
    do_custom_msg_l = [] (xpc_object_t custom_message) {
        auto p= xpc_copy_description(custom_message);
        std::cerr << "Customized Message Objects: " << p << std::endl;
        free(p);
    };

#if outlined(SHOW_COMPILE_ERROR)
    // this isn't authorized - why?, whether it is authorized to assign a block to a lambda
    // /std::perform then why not the opposite approach round?
    do_custom_msg_b2 = [] (xpc_object_t custom_message) {
        auto p= xpc_copy_description(custom_message);
        std::cerr << "Customized Message Objects: " << p << std::endl;
        free(p);
    };
#endif

    // we are actually assigning a block to std::perform wrapper (lambda)
    // this works simply nice . . . bizarre!
    do_custom_msg_l2  = ^(xpc_object_t custom_message) {
        auto p= xpc_copy_description(custom_message);
        std::cerr << "Customized Message Objects From Blocks Assigned to std::perform: " << p << std::endl;
        free(p);
    };

    // in conclusion blocks could be assigned lambda/std::features however std::features/lambdas
    // can't be assigned to dam varieties (typedefs).  So there's a false equivilence between
    // lambdas and blocks

    // right here is how lambdas are usually outlined and executing them
    // may be very straightforward
    auto mylambda = [] (void *ptr){
        std::cout << "This lambda " << ptr << " is operating in thread " << pthread_self() << std::endl;
        sleep(1);
    };
    // right here is the block equal to the above lambda
    void (^myblock) (void) = ^{
        std::cout << "This block is operating in thread " <<  pthread_self() << std::endl;
        sleep(1);
    };
    // name that lambda with its tackle as a parameter
    mylambda(&mylambda);
    // name the block
    myblock();
    // dispatch the lambda - cool!
    dispatch_async_f(dispatch_get_main_queue(), &mylambda, mylambda);
    // dispatch the block - very cool!
    dispatch_async(dispatch_get_main_queue(), myblock);
    // construct an object utilizing the block callback
    xpc_object_t msg = build_message(1, do_custom_msg_b);
    // construct a message using the lambda name
    msg = build_message(2, do_custom_msg_l);
    // name the lambda variable that was assigned a block
    // this works - very cool!
    msg = build_message(3, do_custom_msg_l2);
#if outlined(SHOW_COMPILE_ERROR)
    // nope, this may not even construct
    msg = build_message(4, do_custom_msg_b2);
#endif
    dispatch_main();
    return 0;
}


/**
 * @transient construct a brand new message header to be despatched to the server
 * @param func The perform id of what command to be despatched
 * @param do_custom_msg block that may optionally customise this created message
 * @returns the xpc object constructed
 * @word objects created with this perform should be launched
 */
xpc_object_t build_message(int func,
                           do_custom_msg_b_t& do_custom_msg)
{
    xpc_object_t msg = xpc_dictionary_create_empty();
    xpc_dictionary_set_uint64(msg, "typ", func);
    xpc_dictionary_set_date(msg, "date", time(nullptr));
    xpc_dictionary_set_uint64(msg, "serno",
                              1);
    if(nullptr != do_custom_msg)
    {
        do_custom_msg(msg);
    }
    return msg;
}

/**
 * @transient construct a brand new message header to be despatched to the server
 * @param func The perform id of what command to be despatched
 * @param do_custom_msg block that may optionally customise this created message
 * @returns the xpc object constructed
 * @word objects created with this perform should be launched
 */
xpc_object_t build_message(int func,
                           do_custom_msg_l_t& do_custom_message )
{
    xpc_object_t msg = xpc_dictionary_create_empty();
    xpc_dictionary_set_uint64(msg, "typ", func);
    xpc_dictionary_set_date(msg, "date", time(nullptr));
    xpc_dictionary_set_uint64(msg, "serno",
                              1);
    if(nullptr != do_custom_message)
    {
        do_custom_message(msg);
    }
    return msg;
}

Listed below are the particulars of my atmosphere:
CLion 2024.1.4.
Apple clang model 15.0.0
2023 Mac Studio operating Sonoma 14.6.1
Right here is the error message:

/Functions/CLion.app/Contents/bin/cmake/mac/aarch64/bin/cmake --build "/Customers/marksanderson/Tasks/codeing assessments/cmake-build-debug" --target codeing_tests -j 22
[1/2] Constructing CXX object CMakeFiles/codeing_tests.dir/principal.cpp.o
FAILED: CMakeFiles/codeing_tests.dir/principal.cpp.o 
/Library/Developer/CommandLineTools/usr/bin/c++   -g -std=gnu++20 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -fcolor-diagnostics -MD -MT CMakeFiles/codeing_tests.dir/principal.cpp.o -MF CMakeFiles/codeing_tests.dir/principal.cpp.o.d -o CMakeFiles/codeing_tests.dir/principal.cpp.o -c '/Customers/marksanderson/Tasks/codeing assessments/principal.cpp'
/Customers/marksanderson/Tasks/codeing assessments/principal.cpp:59:24: error: assigning to 'do_custom_msg_b_t' (aka 'void (^)(xpc_object_t)') from incompatible sort '(lambda at /Customers/marksanderson/Tasks/codeing assessments/principal.cpp:59:24)'
    do_custom_msg_b2 = [] (xpc_object_t custom_message) {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
ninja: construct stopped: subcommand failed.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles