catalina – Are there any cases in modern MacOS where you have to put files on the OS’ volume?

Historically I am sure older versions of OSX have sometimes forced me to install apps/files onto the volume/drive the OS is installed on.

Maybe I misremember that but regardless in current versions Catalina onwards, do I have total freedom? I am planning to get a new Mac with the smallest SSD (256Gb) and separately buy a large external SSD drive (2Tb). I don’t want to find that the internal drive is a limiting factor later – I might want to use the internal drive purely for the OS for instance.

recursion – A recursive_transform template function for the multiple parameters cases in C++

This is a follow-up question for A recursive_transform template function for the binary operation cases in C++. Thanks for G. Sliepen’s answer. Based on the mentioned suggestion, I am attempting to improve the extendibility of recursive_transform template function for the multiple parameters cases.

  • recursive_invoke_result template struct and recursive_variadic_invoke_result template struct

    recursive_invoke_result struct is updated with integrating unwrap_level parameter instead of using std::invocable in order to make the logic of recursion be consistent. The recursive_invoke_result struct is focus on the result type of invoking functions with unary input and the recursive_variadic_invoke_result struct deals with the result type of invoking functions with multiple inputs.

  • recursive_transform template function for the multiple parameters cases

    The main part of this post. The multiple parameterized lambda for recursive transform is supported.

    For example, the following code can be compiled.

    std::vector<std::string> test_vector1{ "1", "4", "7" };
    std::vector<std::string> test_vector2{ "2", "5", "8" };
    std::vector<std::string> test_vector3{ "3", "6", "9" };
    std::vector<std::string> test_vector4{ "a", "b", "c" };
    auto output = recursive_transform<1>(
        ()(auto element1, auto element2, auto element3, auto element4) { return element1 + element2 + element3 + element4; },
        test_vector1, test_vector2, test_vector3, test_vector4);
    for (auto&& element : output)
    {
        std::cout << element << std::endl;
    }
    

    The output in the above code is a std::vector<std::string>. The console output:

    123a
    456b
    789c
    

The experimental implementation

  • recursive_invoke_result template struct implementation: recursive_invoke_result struct here integrating unwrap_level parameter. struct recursive_invoke_result<0, F, T> is a kind of partial template specialization which plays the role of recursion termination condition. Whether typename T is a range or not, the type just comes from std::invoke_result_t<F, T> if unwrap_level is 0.

    //  recursive_invoke_result_t implementation
    template<std::size_t, typename, typename>
    struct recursive_invoke_result { };
    
    template<typename T, typename F>
    struct recursive_invoke_result<0, F, T> { using type = std::invoke_result_t<F, T>; };
    
    template<std::size_t unwrap_level, typename F, template<typename...> typename Container, typename... Ts>
    requires (std::ranges::input_range<Container<Ts...>> &&
              requires { typename recursive_invoke_result<unwrap_level - 1, F, std::ranges::range_value_t<Container<Ts...>>>::type; })
    struct recursive_invoke_result<unwrap_level, F, Container<Ts...>>
    {
        using type = Container<typename recursive_invoke_result<unwrap_level - 1, F, std::ranges::range_value_t<Container<Ts...>>>::type>;
    };
    
    template<std::size_t unwrap_level, typename F, typename T>
    using recursive_invoke_result_t = typename recursive_invoke_result<unwrap_level, F, T>::type;
    
  • recursive_variadic_invoke_result template struct implementation: recursive_variadic_invoke_result struct deals with the result type of invoking functions with multiple inputs.

    //  recursive_variadic_invoke_result_t implementation
    template<std::size_t, typename, typename, typename...>
    struct recursive_variadic_invoke_result { };
    
    template<typename F, class...Ts1, template<class...>class Container1, typename... Ts>
    struct recursive_variadic_invoke_result<0, F, Container1<Ts1...>, Ts...>
    {
        using type = std::invoke_result_t<F, Container1<Ts1...>, Ts...>;
    };
    
    template<typename F, class...Ts1, template<class...>class Container1, typename... Ts>
    struct recursive_variadic_invoke_result<1, F, Container1<Ts1...>, Ts...>
    {
        using type = Container1<std::invoke_result_t<F,
            std::ranges::range_value_t<Container1<Ts1...>>,
            std::ranges::range_value_t<Ts>...>>;
    };
    
    template<std::size_t unwrap_level, typename F, class...Ts1, template<class...>class Container1, typename... Ts>
    requires (  std::ranges::input_range<Container1<Ts1...>> &&
                requires { typename recursive_variadic_invoke_result<
                                        unwrap_level - 1,
                                        F,
                                        std::ranges::range_value_t<Container1<Ts1...>>,
                                        std::ranges::range_value_t<Ts>...>::type; })                //  The rest arguments are ranges
    struct recursive_variadic_invoke_result<unwrap_level, F, Container1<Ts1...>, Ts...>
    {
        using type = Container1<
            typename recursive_variadic_invoke_result<
            unwrap_level - 1,
            F,
            std::ranges::range_value_t<Container1<Ts1...>>,
            std::ranges::range_value_t<Ts>...
            >::type>;
    };
    
    template<std::size_t unwrap_level, typename F, typename T1, typename... Ts>
    using recursive_variadic_invoke_result_t = typename recursive_variadic_invoke_result<unwrap_level, F, T1, Ts...>::type;
    
  • transform function for any $n$-ary function: from G. Sliepen’s answer

    template<typename OutputIt, typename NAryOperation, typename InputIt, typename... InputIts>
    OutputIt transform(OutputIt d_first, NAryOperation op, InputIt first, InputIt last, InputIts... rest) {
        while (first != last) {
            *d_first++ = op(*first++, (*rest++)...);
        }
        return d_first;
    }
    
  • The first recursive_transform template function overloading: dealing with unary input transform cases.

    //  recursive_transform implementation (the version with unwrap_level)
    template<std::size_t unwrap_level = 1, class T, class F>
    constexpr auto recursive_transform(const F& f, const T& input)
    {
        if constexpr (unwrap_level > 0)
        {
            recursive_invoke_result_t<unwrap_level, F, T> output{};
            std::ranges::transform(
                std::ranges::cbegin(input),
                std::ranges::cend(input),
                std::inserter(output, std::ranges::end(output)),
                (&f)(auto&& element) { return recursive_transform<unwrap_level - 1>(f, element); }
            );
            return output;
        }
        else
        {
            return f(input);
        }
    }
    
  • The second recursive_transform template function overloading: handling the cases with multiple input function.

    //  recursive_transform for the multiple parameters cases (the version with unwrap_level)
    template<std::size_t unwrap_level = 1, class F, class Arg1, class... Args>
    constexpr auto recursive_transform(const F& f, const Arg1& arg1, const Args&... args)
    {
        if constexpr (unwrap_level > 0)
        {
            recursive_variadic_invoke_result_t<unwrap_level, F, Arg1, Args...> output{};
            transform(
                std::inserter(output, std::ranges::end(output)),
                (&f)(auto&& element1, auto&&... elements) { return recursive_transform<unwrap_level - 1>(f, element1, elements...); },
                std::ranges::cbegin(arg1),
                std::ranges::cend(arg1),
                std::ranges::cbegin(args)...
            );
            return output;
        }
        else
        {
            return f(arg1, args...);
        }
    }
    

The testing code

In the following Godbolt link, the testing code is divide into three parts: unary_test_cases, binary_test_cases and ternary_test_cases.

A Godbolt link is here.

unary_test_cases and binary_test_cases are similar to the previous posts.

Let’s check ternary_test_cases:

void ternary_test_cases()
{
    std::cout << "*****ternary_test_cases*****" << std::endl;

    //  non-nested input test, lambda function applied on input directly
    int test_number = 3;
    std::cout << recursive_transform<0>(
        ()(auto&& element1, auto&& element2, auto&& element3) { return element1 + element2 + element3; },
        test_number, test_number, test_number) << std::endl;
    
    //  nested input test, lambda function applied on input directly
    std::vector<int> test_vector = {
        1, 2, 3
    };
    std::cout << recursive_transform<0>(()(auto element1, auto element2, auto element3)
        {
            return element1.size() + element2.size() + element3.size();
        },
        test_vector, test_vector, test_vector) << std::endl;
    
    //  std::vector<int> -> std::vector<std::string>
    auto recursive_transform_result = recursive_transform<1>(
        ()(int element1, int element2, int element3)->std::string { return std::to_string(element1 + element2 + element3); },
        test_vector, test_vector, test_vector
    );                                                                                  //  For testing
    std::cout << "std::vector<int> -> std::vector<std::string>: " +
        recursive_transform_result.at(1) << std::endl;                                  //  recursive_transform_result.at(0) is a std::string
    
    //  std::vector<string> -> std::vector<int>
    std::cout << "std::vector<string> -> std::vector<int>: "
              << recursive_transform<1>(
            ()(std::string element1, std::string element2, std::string element3) 
                  { return std::atoi((element1 + element2 + element3).c_str()); },
            recursive_transform_result, recursive_transform_result, recursive_transform_result).at(0) + 1 << std::endl;                         //  std::string element to int
    
    //  std::vector<std::vector<int>> -> std::vector<std::vector<std::string>>
    std::vector<decltype(test_vector)> test_vector2 = {
        test_vector, test_vector, test_vector
    };

    auto recursive_transform_result2 = recursive_transform<2>(
        ()(int element1, int element2, int element3)
        { return std::to_string(element1) + std::to_string(element2) + std::to_string(element3); },
        test_vector2, test_vector2, test_vector2
    );                                                                                  //  For testing
    std::cout << "string: " + recursive_transform_result2.at(0).at(0) << std::endl;     // recursive_transform_result.at(0).at(0) is also a std::string
    
    //  std::deque<int> -> std::deque<std::string>
    std::deque<int> test_deque;
    test_deque.push_back(1);
    test_deque.push_back(1);
    test_deque.push_back(1);

    auto recursive_transform_result3 = recursive_transform<1>(
        ()(int element1, int element2, int element3)
        { return std::to_string(element1) + std::to_string(element2) + std::to_string(element3); },
        test_deque, test_deque, test_deque);                            //  For testing

    std::cout << "string: " + recursive_transform_result3.at(0) << std::endl;
    
    //  std::deque<std::deque<int>> -> std::deque<std::deque<std::string>>
    std::deque<decltype(test_deque)> test_deque2;
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);

    auto recursive_transform_result4 = recursive_transform<2>(
        ()(int element1, int element2, int element3)
        { return std::to_string(element1) + std::to_string(element2) + std::to_string(element3); },
        test_deque2, test_deque2, test_deque2);                         //  For testing

    std::cout << "string: " + recursive_transform_result4.at(0).at(0) << std::endl;
    
    //  std::list<int> -> std::list<std::string>
    std::list<int> test_list = { 1, 2, 3, 4 };
    auto recursive_transform_result5 = recursive_transform<1>(
        ()(int element1, int element2, int element3)
        { return std::to_string(element1) + std::to_string(element2) + std::to_string(element3); },
        test_list, test_list, test_list);                               //  For testing
    std::cout << "string: " + recursive_transform_result5.front() << std::endl;


    //  std::list<std::list<int>> -> std::list<std::list<std::string>>
    std::list<std::list<int>> test_list2 = { test_list, test_list, test_list, test_list };
    auto recursive_transform_result6 = recursive_transform<2>(
        ()(int element1, int element2, int element3)
        { return std::to_string(element1) + std::to_string(element2) + std::to_string(element3); },
        test_list2, test_list2, test_list2);                            //  For testing
    std::cout << "string: " + recursive_transform_result6.front().front() << std::endl;
    return;
}

The output of the testing code above:

*****ternary_test_cases*****
9
9
std::vector<int> -> std::vector<std::string>: 6
std::vector<string> -> std::vector<int>: 334
string: 111
string: 111
string: 111
string: 111
string: 111

Other details

The different container types can be used simultaneously as the parameters of recursive_transform, such as the following example.

std::list<std::string> data1{ "1", "4", "7" };
std::vector<std::string> data2{ "2", "5", "8" };
std::list<std::string> data3{ "3", "6", "9" };
std::list<std::string> data4{ "a", "b", "c" };
auto output = recursive_transform<1>(
    ()(auto element1, auto element2, auto element3, auto element4) { return element1 + element2 + element3 + element4; },
    data1, data2, data3, data4);
std::cout << typeid(output).name() << std::endl;
for (auto&& element : output)
{
    std::cout << element << std::endl;
}

However, the container type of the output (in the case of output is ranges) follows the first input range parameter. Therefore, the type of the container of output is std::list<>.

The output of the testing code above (from clang):

NSt7__cxx114listINS_12basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EEE
123a
456b
789c

All suggestions are welcome.

The summary information:

  • Which question it is a follow-up to?

    A recursive_transform template function for the binary operation cases in C++

  • What changes has been made in the code since last question?

    I am attempting to improve the extendibility of recursive_transform template function for the multiple parameters cases in this post.

  • Why a new review is being asked for?

    If there is any possible improvement, please let me know.

Do fully dressed use cases contain postconditions?

I am trying to solidify my understanding of the definition of a fully dressed use case.

I was asked a question in an interview which was as follows:

Operations contracts are generally written for:

  1. All fully dressed use cases
  2. All use cases
  3. The most complex operations in fully dressed use cases
  4. The most elementary operations in brief use cases
  5. None of the above

I chose 1. All fully dressed use cases though I have a feeling I may be wrong.

Here is what I found after doing a little digging around,

As per the Craig Larman PDF Page 7 and 8

I do not see Postconditions but then again I’m a little confused about the concept of a Fully dressed use case.

part 1

part 2

recursion – A recursive_transform template function for the binary operation cases with execution policy in C++

This is a follow-up question for A recursive_transform template function for the binary operation cases in C++, A recursive_transform Template Function with Unwrap Level for Various Type Arbitrary Nested Iterable Implementation in C++, A recursive_transform Template Function Implementation with std::invocable Concept and Execution Policy in C++ and A recursive_print Function For Various Type Arbitrary Nested Iterable Implementation in C++. The execution policy parameter is available since C++17. I am trying to add this into the recursive_transform template function. Considering std::for_each working on more than one range of iterators, the boost::zip_iterator is used here. The experimental version code is as below.

The experimental implementation

  • recursive_transform template function for the binary operation cases with execution policy:

    #define USE_BOOST_ITERATOR
    #ifdef USE_BOOST_ITERATOR
    #include <boost/iterator/zip_iterator.hpp>
    
    //  recursive_transform for the binary operation cases (the version with unwrap_level, with execution policy)
    template<std::size_t unwrap_level = 1, class ExPo, class T1, class T2, class F>
    requires (std::is_execution_policy_v<std::remove_cvref_t<ExPo>>)
    constexpr auto recursive_transform(ExPo execution_policy, const T1& input1, const T2& input2, const F& f)
    {
        if constexpr (unwrap_level > 0)
        {
            recursive_invoke_result_t2<F, T1, T2> output{};
            assert(input1.size() == input2.size());
            std::mutex mutex;
    
            //  Reference: https://stackoverflow.com/a/10457201/6667035
            //  Reference: https://www.boost.org/doc/libs/1_76_0/libs/iterator/doc/zip_iterator.html
            std::for_each(execution_policy,
                boost::make_zip_iterator(
                    boost::make_tuple(std::ranges::cbegin(input1), std::ranges::cbegin(input2))
                ),
                boost::make_zip_iterator(
                    boost::make_tuple(std::ranges::cend(input1), std::ranges::cend(input2))
                ),
                (&)(auto&& elements)
                {
                    auto result = recursive_transform<unwrap_level - 1>(execution_policy, boost::get<0>(elements), boost::get<1>(elements), f);
                    std::lock_guard lock(mutex);
                    output.emplace_back(std::move(result));
                }
            );
    
            return output;
        }
        else
        {
            return f(input1, input2);
        }
    }
    #endif
    
  • recursive_invoke_result2 struct implementation: in order to determine the type of output, recursive_invoke_result2 struct is needed.

    template<typename, typename, typename>
    struct recursive_invoke_result2 { };
    
    template<typename T1, typename T2, std::invocable<T1, T2> F>
    struct recursive_invoke_result2<F, T1, T2> { using type = std::invoke_result_t<F, T1, T2>; };
    
    //  Ref: https://stackoverflow.com/a/66821371/6667035
    template<typename F, class...Ts1, class...Ts2, template<class...>class Container1, template<class...>class Container2>
    requires (
        !std::invocable<F, Container1<Ts1...>, Container2<Ts2...>>&&
        std::ranges::input_range<Container1<Ts1...>>&&
        std::ranges::input_range<Container2<Ts2...>>&&
        requires { typename recursive_invoke_result2<F, std::ranges::range_value_t<Container1<Ts1...>>, std::ranges::range_value_t<Container2<Ts2...>>>::type; })
        struct recursive_invoke_result2<F, Container1<Ts1...>, Container2<Ts2...>>
    {
        using type = Container1<typename recursive_invoke_result2<F, std::ranges::range_value_t<Container1<Ts1...>>, std::ranges::range_value_t<Container2<Ts2...>>>::type>;
    };
    
    template<typename F, typename T1, typename T2>
    using recursive_invoke_result_t2 = typename recursive_invoke_result2<F, T1, T2>::type;
    

The full testing code

//  A recursive_transform template function for the binary operation cases with execution policy in C++

#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <complex>
#include <concepts>
#include <deque>
#include <execution>
#include <exception>
#include <functional>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <mutex>
#include <numeric>
#include <optional>
#include <ranges>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>

//  recursive_print implementation
template<std::ranges::input_range Range>
constexpr auto recursive_print(const Range& input, const int level = 0)
{
    auto output = input;
    std::cout << std::string(level, ' ') << "Level " << level << ":" << std::endl;
    std::ranges::transform(std::ranges::cbegin(input), std::ranges::cend(input), std::ranges::begin(output),
        (level)(auto&& x)
        {
            std::cout << std::string(level, ' ') << x << std::endl;
            return x;
        }
    );
    return output;
}

template<std::ranges::input_range Range> requires (std::ranges::input_range<std::ranges::range_value_t<Range>>)
constexpr auto recursive_print(const Range& input, const int level = 0)
{
    auto output = input;
    std::cout << std::string(level, ' ') << "Level " << level << ":" << std::endl;
    std::ranges::transform(std::ranges::cbegin(input), std::ranges::cend(input), std::ranges::begin(output),
        (level)(auto&& element)
        {
            return recursive_print(element, level + 1);
        }
    );
    return output;
}

//  recursive_invoke_result_t implementation
template<typename, typename>
struct recursive_invoke_result { };

template<typename T, std::invocable<T> F>
struct recursive_invoke_result<F, T> { using type = std::invoke_result_t<F, T>; };

template<typename, typename, typename>
struct recursive_invoke_result2 { };

template<typename T1, typename T2, std::invocable<T1, T2> F>
struct recursive_invoke_result2<F, T1, T2> { using type = std::invoke_result_t<F, T1, T2>; };

template<typename F, template<typename...> typename Container, typename... Ts>
requires (
    !std::invocable<F, Container<Ts...>>&&
    std::ranges::input_range<Container<Ts...>>&&
    requires { typename recursive_invoke_result<F, std::ranges::range_value_t<Container<Ts...>>>::type; })
    struct recursive_invoke_result<F, Container<Ts...>>
{
    using type = Container<typename recursive_invoke_result<F, std::ranges::range_value_t<Container<Ts...>>>::type>;
};

//  Ref: https://stackoverflow.com/a/66821371/6667035
template<typename F, class...Ts1, class...Ts2, template<class...>class Container1, template<class...>class Container2>
requires (
    !std::invocable<F, Container1<Ts1...>, Container2<Ts2...>>&&
    std::ranges::input_range<Container1<Ts1...>>&&
    std::ranges::input_range<Container2<Ts2...>>&&
    requires { typename recursive_invoke_result2<F, std::ranges::range_value_t<Container1<Ts1...>>, std::ranges::range_value_t<Container2<Ts2...>>>::type; })
    struct recursive_invoke_result2<F, Container1<Ts1...>, Container2<Ts2...>>
{
    using type = Container1<typename recursive_invoke_result2<F, std::ranges::range_value_t<Container1<Ts1...>>, std::ranges::range_value_t<Container2<Ts2...>>>::type>;
};

template<typename F, typename T>
using recursive_invoke_result_t = typename recursive_invoke_result<F, T>::type;

template<typename F, typename T1, typename T2>
using recursive_invoke_result_t2 = typename recursive_invoke_result2<F, T1, T2>::type;

//  recursive_transform implementation (the version with unwrap_level)
template<std::size_t unwrap_level = 1, class T, class F>
constexpr auto recursive_transform(const T& input, const F& f)
{
    if constexpr (unwrap_level > 0)
    {
        recursive_invoke_result_t<F, T> output{};
        std::ranges::transform(
            std::ranges::cbegin(input),
            std::ranges::cend(input),
            std::inserter(output, std::ranges::end(output)),
            (&f)(auto&& element) { return recursive_transform<unwrap_level - 1>(element, f); }
        );
        return output;
    }
    else
    {
        return f(input);
    }
}

//  recursive_transform implementation (the version with unwrap_level, with execution policy)
template<std::size_t unwrap_level = 1, class ExPo, class T, class F>
requires (std::is_execution_policy_v<std::remove_cvref_t<ExPo>>)
constexpr auto recursive_transform(ExPo execution_policy, const T& input, const F& f)
{
    if constexpr (unwrap_level > 0)
    {
        recursive_invoke_result_t<F, T> output{};
        std::mutex mutex;

        //  Reference: https://en.cppreference.com/w/cpp/algorithm/for_each
        std::for_each(execution_policy, input.cbegin(), input.cend(),
            (&)(auto&& element)
            {
                auto result = recursive_transform<unwrap_level - 1>(execution_policy, element, f);
                std::lock_guard lock(mutex);
                output.emplace_back(std::move(result));
            }
        );

        return output;
    }
    else
    {
        return f(input);
    }
}

//  recursive_transform for the binary operation cases (the version with unwrap_level)
template<std::size_t unwrap_level = 1, class T1, class T2, class F>
requires (!std::is_execution_policy_v<std::remove_cvref_t<T1>>) //  workaround for gcc: call of overloaded 'recursive_transform<1>(const __pstl::execution::v1::parallel_policy&, std::__cxx11::list<int>&, unary_test_cases_execute_policy()::<lambda(int)>)' is ambiguous
constexpr auto recursive_transform(const T1& input1, const T2& input2, const F& f)
{
    if constexpr (unwrap_level > 0)
    {
        recursive_invoke_result_t2<F, T1, T2> output{};
        std::transform(
            std::ranges::cbegin(input1),
            std::ranges::cend(input1),
            std::ranges::cbegin(input2),
            std::inserter(output, std::ranges::end(output)),
            (&f)(auto&& element1, auto&& element2) { return recursive_transform<unwrap_level - 1>(element1, element2, f); }
        );
        return output;
    }
    else
    {
        return f(input1, input2);
    }
}

#define USE_BOOST_ITERATOR
#ifdef USE_BOOST_ITERATOR
#include <boost/iterator/zip_iterator.hpp>

//  recursive_transform for the binary operation cases (the version with unwrap_level, with execution policy)
template<std::size_t unwrap_level = 1, class ExPo, class T1, class T2, class F>
requires (std::is_execution_policy_v<std::remove_cvref_t<ExPo>>)
constexpr auto recursive_transform(ExPo execution_policy, const T1& input1, const T2& input2, const F& f)
{
    if constexpr (unwrap_level > 0)
    {
        recursive_invoke_result_t2<F, T1, T2> output{};
        assert(input1.size() == input2.size());
        std::mutex mutex;

        //  Reference: https://stackoverflow.com/a/10457201/6667035
        //  Reference: https://www.boost.org/doc/libs/1_76_0/libs/iterator/doc/zip_iterator.html
        std::for_each(execution_policy,
            boost::make_zip_iterator(
                boost::make_tuple(std::ranges::cbegin(input1), std::ranges::cbegin(input2))
            ),
            boost::make_zip_iterator(
                boost::make_tuple(std::ranges::cend(input1), std::ranges::cend(input2))
            ),
            (&)(auto&& elements)
            {
                auto result = recursive_transform<unwrap_level - 1>(execution_policy, boost::get<0>(elements), boost::get<1>(elements), f);
                std::lock_guard lock(mutex);
                output.emplace_back(std::move(result));
            }
        );

        return output;
    }
    else
    {
        return f(input1, input2);
    }
}
#endif

void unary_test_cases();
void unary_test_cases_execute_policy();
void binary_test_cases();
void binary_test_cases_execute_policy();

int main()
{
    unary_test_cases();
    unary_test_cases_execute_policy();
    binary_test_cases();
    binary_test_cases_execute_policy();
    return 0;
}

void unary_test_cases()
{
    //  non-nested input test, lambda function applied on input directly
    int test_number = 3;
    std::cout << recursive_transform<0>(test_number, ()(auto&& element) { return element + 1; }) << std::endl;

    //  nested input test, lambda function applied on input directly
    std::vector<int> test_vector = {
        1, 2, 3
    };
    std::cout << recursive_transform<0>(test_vector, ()(auto element)
        {
            element.push_back(4);
            element.push_back(5);
            return element;
        }).size() << std::endl;

        //  std::vector<int> -> std::vector<std::string>
        auto recursive_transform_result = recursive_transform<1>(
            test_vector,
            ()(int x)->std::string { return std::to_string(x); }
        );                                                                                  //  For testing

        std::cout << "std::vector<int> -> std::vector<std::string>: " +
            recursive_transform_result.at(0) << std::endl;                                  //  recursive_transform_result.at(0) is a std::string

        //  std::vector<string> -> std::vector<int>
        std::cout << "std::vector<string> -> std::vector<int>: "
            << recursive_transform<1>(
                recursive_transform_result,
                ()(std::string x) { return std::atoi(x.c_str()); }).at(0) + 1 << std::endl; //  std::string element to int

        //  std::vector<std::vector<int>> -> std::vector<std::vector<std::string>>
        std::vector<decltype(test_vector)> test_vector2 = {
            test_vector, test_vector, test_vector
        };

        auto recursive_transform_result2 = recursive_transform<2>(
            test_vector2,
            ()(int x)->std::string { return std::to_string(x); }
        );                                                                                  //  For testing

        std::cout << "string: " + recursive_transform_result2.at(0).at(0) << std::endl;     // recursive_transform_result.at(0).at(0) is also a std::string

        //  std::deque<int> -> std::deque<std::string>
        std::deque<int> test_deque;
        test_deque.push_back(1);
        test_deque.push_back(1);
        test_deque.push_back(1);

        auto recursive_transform_result3 = recursive_transform<1>(
            test_deque,
            ()(int x)->std::string { return std::to_string(x); });                          //  For testing

        std::cout << "string: " + recursive_transform_result3.at(0) << std::endl;

        //  std::deque<std::deque<int>> -> std::deque<std::deque<std::string>>
        std::deque<decltype(test_deque)> test_deque2;
        test_deque2.push_back(test_deque);
        test_deque2.push_back(test_deque);
        test_deque2.push_back(test_deque);

        auto recursive_transform_result4 = recursive_transform<2>(
            test_deque2,
            ()(int x)->std::string { return std::to_string(x); });                          //  For testing

        std::cout << "string: " + recursive_transform_result4.at(0).at(0) << std::endl;

        //  std::list<int> -> std::list<std::string>
        std::list<int> test_list = { 1, 2, 3, 4 };
        auto recursive_transform_result5 = recursive_transform<1>(
            test_list,
            ()(int x)->std::string { return std::to_string(x); });                          //  For testing
        std::cout << "string: " + recursive_transform_result5.front() << std::endl;


        //  std::list<std::list<int>> -> std::list<std::list<std::string>>
        std::list<std::list<int>> test_list2 = { test_list, test_list, test_list, test_list };
        auto recursive_transform_result6 = recursive_transform<2>(
            test_list2,
            ()(int x)->std::string { return std::to_string(x); });                          //  For testing
        std::cout << "string: " + recursive_transform_result6.front().front() << std::endl;
        return;
}

void unary_test_cases_execute_policy()
{
    //  non-nested input test, lambda function applied on input directly
    int test_number = 3;
    std::cout << recursive_transform<0>(std::execution::par, test_number, ()(auto&& element) { return element + 1; }) << std::endl;

    //  nested input test, lambda function applied on input directly
    std::vector<int> test_vector = {
        1, 2, 3
    };
    std::cout << recursive_transform<0>(std::execution::par, test_vector, ()(auto element)
        {
            element.push_back(4);
            element.push_back(5);
            return element;
        }).size() << std::endl;

    //  std::vector<int> -> std::vector<std::string>
    auto recursive_transform_result = recursive_transform<1>(
        std::execution::par,
        test_vector,
        ()(int x)->std::string { return std::to_string(x); }
    );                                                                                  //  For testing

    std::cout << "std::vector<int> -> std::vector<std::string>: " +
        recursive_transform_result.at(0) << std::endl;                                  //  recursive_transform_result.at(0) is a std::string

    //  std::vector<string> -> std::vector<int>
    std::cout << "std::vector<string> -> std::vector<int>: "
        << recursive_transform<1>(
            std::execution::par,
            recursive_transform_result,
            ()(std::string x) { return std::atoi(x.c_str()); }).at(0) + 1 << std::endl; //  std::string element to int

    //  std::vector<std::vector<int>> -> std::vector<std::vector<std::string>>
    std::vector<decltype(test_vector)> test_vector2 = {
        test_vector, test_vector, test_vector
    };

    auto recursive_transform_result2 = recursive_transform<2>(
        std::execution::par,
        test_vector2,
        ()(int x)->std::string { return std::to_string(x); }
    );                                                                                  //  For testing

    std::cout << "string: " + recursive_transform_result2.at(0).at(0) << std::endl;     // recursive_transform_result.at(0).at(0) is also a std::string

    //  std::deque<int> -> std::deque<std::string>
    std::deque<int> test_deque;
    test_deque.push_back(1);
    test_deque.push_back(1);
    test_deque.push_back(1);

    auto recursive_transform_result3 = recursive_transform<1>(
        std::execution::par,
        test_deque,
        ()(int x)->std::string { return std::to_string(x); });                          //  For testing

    std::cout << "string: " + recursive_transform_result3.at(0) << std::endl;

    //  std::deque<std::deque<int>> -> std::deque<std::deque<std::string>>
    std::deque<decltype(test_deque)> test_deque2;
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);

    auto recursive_transform_result4 = recursive_transform<2>(
        std::execution::par,
        test_deque2,
        ()(int x)->std::string { return std::to_string(x); });                          //  For testing

    std::cout << "string: " + recursive_transform_result4.at(0).at(0) << std::endl;

    //  std::list<int> -> std::list<std::string>
    std::list<int> test_list = { 1, 2, 3, 4 };
    auto recursive_transform_result5 = recursive_transform<1>(
        std::execution::par,
        test_list,
        ()(int x)->std::string { return std::to_string(x); });                          //  For testing
    std::cout << "string: " + recursive_transform_result5.front() << std::endl;


    //  std::list<std::list<int>> -> std::list<std::list<std::string>>
    std::list<std::list<int>> test_list2 = { test_list, test_list, test_list, test_list };
    auto recursive_transform_result6 = recursive_transform<2>(
        std::execution::par,
        test_list2,
        ()(int x)->std::string { return std::to_string(x); });                          //  For testing
    std::cout << "string: " + recursive_transform_result6.front().front() << std::endl;
    return;
}

void binary_test_cases()
{
    //  std::vector<int>
    std::vector<int> a{ 1, 2, 3 }, b{ 4, 5, 6 };
    auto result1 = recursive_transform<1>(a, b, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result1)
    {
        std::cout << element << std::endl;
    }

    //  std::vector<std::vector<int>>
    std::vector<decltype(a)> c{ a, a, a }, d{ b, b, b };
    auto result2 = recursive_transform<2>(c, d, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result2);

    //  std::deque<int>
    std::deque<int> test_deque;
    test_deque.push_back(1);
    test_deque.push_back(1);
    test_deque.push_back(1);

    auto result3 = recursive_transform<1>(test_deque, test_deque, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result3)
    {
        std::cout << element << std::endl;
    }

    //  std::deque<std::deque<int>>
    std::deque<decltype(test_deque)> test_deque2;
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    auto result4 = recursive_transform<2>(test_deque2, test_deque2, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result4);

    //  std::list<int>
    std::list<int> test_list = { 1, 2, 3, 4 };
    auto result5 = recursive_transform<1>(test_list, test_list, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result5)
    {
        std::cout << element << std::endl;
    }

    //  std::list<std::list<int>>
    std::list<std::list<int>> test_list2 = { test_list, test_list, test_list, test_list };
    auto result6 = recursive_transform<2>(test_list2, test_list2, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result6);
    return;
}

void binary_test_cases_execute_policy()
{
    //  std::vector<int>
    std::vector<int> a{ 1, 2, 3 }, b{ 4, 5, 6 };
    auto result1 = recursive_transform<1>(std::execution::par, a, b, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result1)
    {
        std::cout << element << std::endl;
    }

    //  std::vector<std::vector<int>>
    std::vector<decltype(a)> c{ a, a, a }, d{ b, b, b };
    auto result2 = recursive_transform<2>(std::execution::par, c, d, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result2);

    //  std::deque<int>
    std::deque<int> test_deque;
    test_deque.push_back(1);
    test_deque.push_back(1);
    test_deque.push_back(1);

    auto result3 = recursive_transform<1>(std::execution::par, test_deque, test_deque, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result3)
    {
        std::cout << element << std::endl;
    }

    //  std::deque<std::deque<int>>
    std::deque<decltype(test_deque)> test_deque2;
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    auto result4 = recursive_transform<2>(std::execution::par, test_deque2, test_deque2, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result4);

    //  std::list<int>
    std::list<int> test_list = { 1, 2, 3, 4 };
    auto result5 = recursive_transform<1>(std::execution::par, test_list, test_list, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result5)
    {
        std::cout << element << std::endl;
    }

    //  std::list<std::list<int>>
    std::list<std::list<int>> test_list2 = { test_list, test_list, test_list, test_list };
    auto result6 = recursive_transform<2>(std::execution::par, test_list2, test_list2, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result6);
    return;
}

A Godbolt link is here.

All suggestions are welcome.

The summary information:

java – How does Dependency Inversion solve switch cases?

I want to understand how Dependency Inversion gets rid of switch cases.

Consider a service that needs to communicate with several databases.

class StockUpdater {
  private final DataStore datastore;
  public StockUpdater(DataStore datastore) {
    this.datastore = datastore;
  }
  public void update(StockItem item, int quantity){
    datastore.update(item, quantity);
  }
}

public interface DataStore {
  update(StockItem item, int quanity)
}

public class PostgresAdapter implements DataStore {
...
  public void update(StockItem item, int quantity) {
    // Add item to database
  }
}

public class MariaDBAdapter implements DataStore {
...
  public void update(StockItem item, int quantity) {
    // Add item to database
  }
}

We remembered our friend abstraction and used interface. Whereas in the past, we might have used hideous if/else or switch statements instantiating for instances new MariaDBAdapter.
Now I understand that we solved this issue by using an interface and taking the logic (if/else conditions ) out of the class stockUpdater and the update() method; however, I thought we shift the problem. Since we need to provide a Datastore when we create a StockUpdater. And this needs an again a condition when to create a PostgresAdapter or a MariaDBAdapter.

it would just be

DataStore myDatastore = null 

if (...){
  myDatastore  = new PostgresAdapter()
}
else {
  myDatastore  = new MariaDBAdapter()
}
StockUpdater myUpdater = new StockUpdater(myDatastore)

...

If my goal is to get rid of tedious if/else conditions, this looks quite the same. If I wanted to take the logic out of StockUpdater, then sure, this is great.

I hope I made myself clear. I might have a thinking blockage. My question how did Dependency Inversion gets rid of switch cases? Or what I am missing in my reasoning.

recursion – A recursive_transform template function for the binary operation cases in C++

This is a follow-up question for A recursive_transform Template Function with Unwrap Level for Various Type Arbitrary Nested Iterable Implementation in C++ and A recursive_print Function For Various Type Arbitrary Nested Iterable Implementation in C++. Besides the usage with single Ranges input like recursive_transform<1>(Ranges, Lambda), I am attempting to extend recursive_transform function to deal with the binary operation cases recursive_transform<>(Ranges1, Ranges2, Lambda) which Lambda here could take two inputs. For example:

std::vector<int> a{ 1, 2, 3 }, b{ 4, 5, 6 };
auto result1 = recursive_transform<1>(a, b, ()(int element1, int element2) { return element1 + element2; });
for (auto&& element : result1)
{
    std::cout << element << std::endl;
}

This code can be compiled and the output:

5
7
9

The experimental implementation

  • recursive_invoke_result2 struct implementation: in order to determine the type of output, recursive_invoke_result2 struct is needed.

    template<typename, typename, typename>
    struct recursive_invoke_result2 { };
    
    template<typename T1, typename T2, std::invocable<T1, T2> F>
    struct recursive_invoke_result2<F, T1, T2> { using type = std::invoke_result_t<F, T1, T2>; };
    
    //  Ref: https://stackoverflow.com/a/66821371/6667035
    template<typename F, class...Ts1, class...Ts2, template<class...>class Container1, template<class...>class Container2>
    requires (
        !std::invocable<F, Container1<Ts1...>, Container2<Ts2...>>&&
        std::ranges::input_range<Container1<Ts1...>>&&
        std::ranges::input_range<Container2<Ts2...>>&&
        requires { typename recursive_invoke_result2<F, std::ranges::range_value_t<Container1<Ts1...>>, std::ranges::range_value_t<Container2<Ts2...>>>::type; })
        struct recursive_invoke_result2<F, Container1<Ts1...>, Container2<Ts2...>>
    {
        using type = Container1<typename recursive_invoke_result2<F, std::ranges::range_value_t<Container1<Ts1...>>, std::ranges::range_value_t<Container2<Ts2...>>>::type>;
    };
    
    template<typename F, typename T1, typename T2>
    using recursive_invoke_result_t2 = typename recursive_invoke_result2<F, T1, T2>::type;
    
  • recursive_transform for the binary operation cases implementation:

    //  recursive_transform for the binary operation cases (the version with unwrap_level)
    template<std::size_t unwrap_level = 1, class T1, class T2, class F>
    constexpr auto recursive_transform(const T1& input1, const T2& input2, const F& f)
    {
        if constexpr (unwrap_level > 0)
        {
            recursive_invoke_result_t2<F, T1, T2> output{};
            std::transform(
                std::ranges::cbegin(input1),
                std::ranges::cend(input1),
                std::ranges::cbegin(input2),
                std::inserter(output, std::ranges::end(output)),
                (&f)(auto&& element1, auto&& element2) { return recursive_transform<unwrap_level - 1>(element1, element2, f); }
            );
            return output;
        }
        else
        {
            return f(input1, input2);
        }
    }
    

The full testing code

//  A recursive_transform template function for the binary operation cases in C++

#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <complex>
#include <concepts>
#include <deque>
#include <execution>
#include <exception>
#include <functional>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <mutex>
#include <numeric>
#include <optional>
#include <ranges>
#include <stdexcept>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>

//  recursive_print implementation
template<std::ranges::input_range Range>
constexpr auto recursive_print(const Range& input, const int level = 0)
{
    auto output = input;
    std::cout << std::string(level, ' ') << "Level " << level << ":" << std::endl;
    std::ranges::transform(std::ranges::cbegin(input), std::ranges::cend(input), std::ranges::begin(output),
        (level)(auto&& x)
        {
            std::cout << std::string(level, ' ') << x << std::endl;
            return x;
        }
    );
    return output;
}

template<std::ranges::input_range Range> requires (std::ranges::input_range<std::ranges::range_value_t<Range>>)
constexpr auto recursive_print(const Range& input, const int level = 0)
{
    auto output = input;
    std::cout << std::string(level, ' ') << "Level " << level << ":" << std::endl;
    std::ranges::transform(std::ranges::cbegin(input), std::ranges::cend(input), std::ranges::begin(output),
        (level)(auto&& element)
        {
            return recursive_print(element, level + 1);
        }
    );
    return output;
}

//  recursive_invoke_result_t implementation
template<typename, typename>
struct recursive_invoke_result { };

template<typename T, std::invocable<T> F>
struct recursive_invoke_result<F, T> { using type = std::invoke_result_t<F, T>; };

template<typename, typename, typename>
struct recursive_invoke_result2 { };

template<typename T1, typename T2, std::invocable<T1, T2> F>
struct recursive_invoke_result2<F, T1, T2> { using type = std::invoke_result_t<F, T1, T2>; };

template<typename F, template<typename...> typename Container, typename... Ts>
requires (
    !std::invocable<F, Container<Ts...>>&&
    std::ranges::input_range<Container<Ts...>>&&
    requires { typename recursive_invoke_result<F, std::ranges::range_value_t<Container<Ts...>>>::type; })
    struct recursive_invoke_result<F, Container<Ts...>>
{
    using type = Container<typename recursive_invoke_result<F, std::ranges::range_value_t<Container<Ts...>>>::type>;
};

//  Ref: https://stackoverflow.com/a/66821371/6667035
template<typename F, class...Ts1, class...Ts2, template<class...>class Container1, template<class...>class Container2>
requires (
    !std::invocable<F, Container1<Ts1...>, Container2<Ts2...>>&&
    std::ranges::input_range<Container1<Ts1...>>&&
    std::ranges::input_range<Container2<Ts2...>>&&
    requires { typename recursive_invoke_result2<F, std::ranges::range_value_t<Container1<Ts1...>>, std::ranges::range_value_t<Container2<Ts2...>>>::type; })
    struct recursive_invoke_result2<F, Container1<Ts1...>, Container2<Ts2...>>
{
    using type = Container1<typename recursive_invoke_result2<F, std::ranges::range_value_t<Container1<Ts1...>>, std::ranges::range_value_t<Container2<Ts2...>>>::type>;
};

template<typename F, typename T>
using recursive_invoke_result_t = typename recursive_invoke_result<F, T>::type;

template<typename F, typename T1, typename T2>
using recursive_invoke_result_t2 = typename recursive_invoke_result2<F, T1, T2>::type;

//  recursive_transform implementation (the version with unwrap_level)
template<std::size_t unwrap_level = 1, class T, class F>
constexpr auto recursive_transform(const T& input, const F& f)
{
    if constexpr (unwrap_level > 0)
    {
        recursive_invoke_result_t<F, T> output{};
        std::ranges::transform(
            std::ranges::cbegin(input),
            std::ranges::cend(input),
            std::inserter(output, std::ranges::end(output)),
            (&f)(auto&& element) { return recursive_transform<unwrap_level - 1>(element, f); }
        );
        return output;
    }
    else
    {
        return f(input);
    }
}

//  recursive_transform implementation (the version with unwrap_level, with execution policy)
template<std::size_t unwrap_level = 1, class ExPo, class T, class F>
requires (std::is_execution_policy_v<std::remove_cvref_t<ExPo>>)
constexpr auto recursive_transform(ExPo execution_policy, const T& input, const F& f)
{
    if constexpr (unwrap_level > 0)
    {
        recursive_invoke_result_t<F, T> output{};
        std::mutex mutex;

        //  Reference: https://en.cppreference.com/w/cpp/algorithm/for_each
        std::for_each(execution_policy, input.cbegin(), input.cend(),
            (&)(auto&& element)
            {
                auto result = recursive_transform<unwrap_level - 1>(execution_policy, element, f);
                std::lock_guard lock(mutex);
                output.emplace_back(std::move(result));
            }
        );

        return output;
    }
    else
    {
        return f(input);
    }
}

//  recursive_transform for the binary operation cases (the version with unwrap_level)
template<std::size_t unwrap_level = 1, class T1, class T2, class F>
constexpr auto recursive_transform(const T1& input1, const T2& input2, const F& f)
{
    if constexpr (unwrap_level > 0)
    {
        recursive_invoke_result_t2<F, T1, T2> output{};
        std::transform(
            std::ranges::cbegin(input1),
            std::ranges::cend(input1),
            std::ranges::cbegin(input2),
            std::inserter(output, std::ranges::end(output)),
            (&f)(auto&& element1, auto&& element2) { return recursive_transform<unwrap_level - 1>(element1, element2, f); }
        );
        return output;
    }
    else
    {
        return f(input1, input2);
    }
}

void binary_test_cases();

int main()
{
    binary_test_cases();
    return 0;
}

void binary_test_cases()
{
    //  std::vector<int>
    std::vector<int> a{ 1, 2, 3 }, b{ 4, 5, 6 };
    auto result1 = recursive_transform<1>(a, b, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result1)
    {
        std::cout << element << std::endl;
    }

    //  std::vector<std::vector<int>>
    std::vector<decltype(a)> c{ a, a, a }, d{ b, b, b };
    auto result2 = recursive_transform<2>(c, d, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result2);

    //  std::deque<int>
    std::deque<int> test_deque;
    test_deque.push_back(1);
    test_deque.push_back(1);
    test_deque.push_back(1);

    auto result3 = recursive_transform<1>(test_deque, test_deque, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result3)
    {
        std::cout << element << std::endl;
    }

    //  std::deque<std::deque<int>>
    std::deque<decltype(test_deque)> test_deque2;
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    auto result4 = recursive_transform<2>(test_deque2, test_deque2, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result4);

    //  std::list<int>
    std::list<int> test_list = { 1, 2, 3, 4 };
    auto result5 = recursive_transform<1>(test_list, test_list, ()(int element1, int element2) { return element1 + element2; });
    for (auto&& element : result5)
    {
        std::cout << element << std::endl;
    }

    //  std::list<std::list<int>>
    std::list<std::list<int>> test_list2 = { test_list, test_list, test_list, test_list };
    auto result6 = recursive_transform<2>(test_list2, test_list2, ()(int element1, int element2) { return element1 + element2; });
    recursive_print(result6);
    return;
}

A Godbolt link is here.

All suggestions are welcome.

The summary information:

forms – Is it OK to break with a design system in certain cases?

I think your instincts are correct. A 36-question form in a narrow modal popup window could create a number of challenges:

  1. What if the user accidentally clicks outside of the window and closes it?
  2. Lengthy scrolling in a modal window is a poor experience.
  3. What does this look like on mobile (if that’s a consideration)?

Consistency is definitely one of the most important UX heuristics, but contemporary UX thought leadership advises to balance consistency with flexibility:

It’s natural that designers look for consistency and try to build
visual systems. However, when focusing on building a consistent
experience, it’s easy for the goals of an end user take a back seat
which ultimately compromises the experience we set out to improve.
Flexibility is often seen at odds with consistency, but for a design
system to scale efficiently and effectively both need to be balanced.
How they’re balanced depends on the personas and workflows for your
products.

You might need to convince your leadership that breaking with the design system is the right thing for the user. If they are not open to this at first, go ahead and implement the questionnaire in a modal and watch the abandonment rate. Suggest testing a full-page version in an A/B test and see if you get better results.

Does DelaunayMesh use exact computations? What is the treatment of non-generic cases?

Computing Delaunay complexes can be sensitive to numerical instabilities, especially in higher dimensions. I would like to know how much I can rely on Mathematica’s answers when using DelaunayMesh. There are two questions:

  1. Are exact computations used when constructing the mesh? Or is the computation numerical?

  2. How does it deal with non-generic cases, when we have, e.g., four points lying on a circle? I know that it triangulates the squares (or n-gons in general). But is it done just arbitrarily or is there some careful treatment implemented, like the Simulation of Simplicity method?

c++ – I m getting a error for this code. Two test cases are giving a TLE. Why?

This code is working well for majority of test cases, but there’s one case where the input vector is only containing zeroes, for which it is not working out, I dry runned the code and it seemed to work. I couldn’t figure out why it is not working?

(Problem)https://leetcode.com/problems/3sum/

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
         vector<vector<int> > v;
        int n=nums.size();
        if(n<3)
            return {};
        
        sort(nums.begin(),nums.end());

for (int i = 0; i < n; ++i)
    {
        int target = - nums(i);
        int left = i + 1;
        int right = n - 1;
        while (left <right)
        {
            int  sum = nums(left) + nums(right);
            if (sum == target)
            {
                vector<int> v1;
                v1.push_back(nums(i));
                v1.push_back(nums(left));
                v1.push_back(nums(right));
                vector<vector<int> >:: iterator it;
                it = find(v.begin(), v.end(), v1);
                if (it == v.end())
                {
                    v.push_back(v1);
                }
                left++;
                right--;
            }
            else
            {
                if (sum < target)
                {
                    left++;
                }
                else
                {
                    right--;
                }
            }
        }
    }     
    return v; 
    }
};
        
   

rt.representation theory – Are there cases in which the Weyl group _does_ act on the flag variety/springer fiber?

In nearly every reference on the classical springer correspondence (for example Chriss/Ginzburg’s book on Complex Geometry) it is stated that the action of the Weyl Group on the homology of the springer fiber is not induced by an action of the Weyl group on the fiber itself. But I couldn’t find any reference or general statement that would make this precise (and I’m just learning about geometric representation theory so I don’t have any good intuition/working knowledge).

For concreteness (and I think this should be a simpler case), consider the springer fiber over zero — then $mathcal{B}_0 = mathcal{B} = G/B$ is the flag varitey (where $B$ is a Borel subalgebra). Now there is an action of the Weyl group $W$ on the quotient $G/T$ (where $Tsubseteq B$ is a maximal torus, which allows to write $W = N_G(T)/T$). Now in Yun’s notes, (1.5.4), he writes that the map $G/Tto G/B$ is an “affine space bundle”, that this implies that the their homologies are isomorphic and that under this isomorphism, the action of $W$ on $H(G/T)$ gives the springer action of $W$ on $H(mathcal{B})$ (I couldn’t find a reference for that though). But I don’t see why there should be no way to use this projection to define an action of $W$ on $mathcal{B}$.
Also, in “Schubert cells and cohomology of the spaces $G/P$” (1973), Bernstein Gelfand and Gelfand construct in chapter 5 a correspondence that gives rise to the springer action. I was hoping that this very explicit construction in the paper would shed some more light on what’s going on, but I haven’t been able to do that myself.

Any help, and also references, are really appreciated.