none
How to use List(T).FindIndex with c++ RRS feed

  • Question

  • I'm trying to use this method with a List<String^> but it wants a Predicate as an agrument and I can't find any documentation for declaring a predicate in c++.   This is what I have:

    Predicate<String^> ^myPred;
    myPred = gcnew Predicate<String^>();
    Int32 index = plugins->FindIndex(myPred);

    I get an error that:

    Error    3    error C3350: 'System::Predicate<T>' : a delegate constructor expects 2 argument(s

    Also, why are there so few c++ examples and so many c# examples?   Very frustrating!!!

    Saturday, March 8, 2014 12:53 AM

Answers

  • Use this syntax: ‘gcnew Predicate<String^>( this, &myForm::matchedString )’.

    According to current documentation, lambda expressions cannot be used in this case.

    Saturday, March 8, 2014 8:05 PM
  • Well, you have to store searchTerm somewhere and using a static variable is not exactly pretty indeed. You could create a separate class to deal with all this:

    ref class SearchTextPredicate {
        String ^searchTerm;
        bool Match(String^ s) {
            return (s == searchTerm);
        }
    public:
        SearchTextPredicate(String ^searchTerm) : searchTerm(searchTerm) {
        }
        operator Predicate<String^>^() {
            return gcnew Predicate<String ^>(this, &SearchTextPredicate::Match);
        }
    };
    
    void example() {
        Console::WriteLine(listToSearch->FindIndex(gcnew SearchTextPredicate("bar")));
    }
    
    This is what a lambda expression does behind the covers.

    Sunday, March 9, 2014 7:34 AM
    Moderator

All replies

  • Thanks for the link.   I had already seen that one and it's close but not exactly what I was looking for.   Since I only had a List of Strings and not a custom class, that was confusing me.   Also confusing was how to pass in another string to compare.   I ended up adding a String member to my class to hold the search term for the delegate function.   The search term and the function itself had to be static to get this to work.   Here's what the code that works looks like:

    public ref class myForm : public System::Windows::Forms::Form
     {
    
    private: static String ^searchTerm;
    
    private: static bool matchedString(String^ s) {
                 if (s == searchTerm) return true;
                 else return false;
    }
    
    private: System::Void someFunction()
    {
    ...
    private: List<String^>^ listToSearch;
    searchTerm ="something to find";
    Int32 ^index = listToSearch->FindIndex(gcnew Predicate<String^>(&matchedString));
    ...
    }


    I tried it with non-static members like the following code, but this gave me the "a delegate constructor expects 2 argument(s)" error:

    public ref class myForm : public System::Windows::Forms::Form
     {
    
    private: String ^searchTerm;
    
    private: bool matchedString(String^ s) {
                 if (s == searchTerm) return true;
                 else return false;
    }
    
    private: System::Void someFunction()
    {
    ...
    private: List<String^>^ listToSearch;
    searchTerm ="something to find";
    Int32 ^index = listToSearch->FindIndex(gcnew Predicate<String^>(this, &matchedString));
    ...
    }


    Another questions I have: Is this possible with a lambda instead of a separate comparison function?  I would like to just code it like this:

    public ref class myForm : public System::Windows::Forms::Form { private: System::Void someFunction() { ... private: List<String^>^ listToSearch;
    String ^ mySearch; Int32 ^index = listToSearch->FindIndex(gcnew Predicate<String^>(this, [mySearch](String ^s)->bool { if (s == mySearch){ return true; } else { return false; }})); ... }


    But this gives the errors:

    error C1001: An internal error has occurred in the compiler
    Intellisense: a local lambda is not allowed in a member function of a managed class

    Thanks for the help!




    Saturday, March 8, 2014 5:28 PM
  • Use this syntax: ‘gcnew Predicate<String^>( this, &myForm::matchedString )’.

    According to current documentation, lambda expressions cannot be used in this case.

    Saturday, March 8, 2014 8:05 PM
  • That works, thanks!  Too bad about the lambda.
    Sunday, March 9, 2014 4:31 AM
  • Is there any way to avoid using the member vairable to hold the searchTerm for comparison?

    Sunday, March 9, 2014 4:40 AM
  • Well, you have to store searchTerm somewhere and using a static variable is not exactly pretty indeed. You could create a separate class to deal with all this:

    ref class SearchTextPredicate {
        String ^searchTerm;
        bool Match(String^ s) {
            return (s == searchTerm);
        }
    public:
        SearchTextPredicate(String ^searchTerm) : searchTerm(searchTerm) {
        }
        operator Predicate<String^>^() {
            return gcnew Predicate<String ^>(this, &SearchTextPredicate::Match);
        }
    };
    
    void example() {
        Console::WriteLine(listToSearch->FindIndex(gcnew SearchTextPredicate("bar")));
    }
    
    This is what a lambda expression does behind the covers.

    Sunday, March 9, 2014 7:34 AM
    Moderator
  • Thanks, that's a nice solution.    I'm surprised that the String class doesn't already have a Predicate interface.    I'm a noob to CLI but this seems like it should have been easier.   Maybe I should just switch to C#.   Seems like that language as far more support at MSDN.
    Sunday, March 9, 2014 4:38 PM
  • It's certainly easier to use FindIndex from C#, this and many other methods have been added in C# 2.0 and they were intended to be used with anonymous methods (and now lambda expressions).

    Back when C++/CLI was created there were no lambda expressions in standard C++ so C++/CLI doesn't have lambda expressions either. It may be possible to extend C++ 11 lambda expressions to C++/CLI but that's yet to happen. Given that C++/CLI's primary purpose in life is to act as "glue" between the managed and native world I'm not sure if there's enough interest for that.

    Monday, March 10, 2014 5:42 AM
    Moderator