locked
Using "->Find" on a "List" in Visual C++ RRS feed

  • Question

  • I'm trying to teach myself Visual C++ and I've written the following class in Visual C++:

    public ref class EntityStruc{
    	public:
    		String^ Entity;
    		String^ System;
    		String^ Type;
    	public:
    		~EntityStruc(){
    		}
    		EntityStruc(String^ EntityIn, String^ SystemIn, String^ TypeIn){
    				this->Entity = EntityIn;
    				this->System = SystemIn;
    				this->Type = TypeIn;
    		}
    };

    And then used that definition in a routine that looks something like this:

    void Fill(List<EntityStruc^>^ EntityTable){
    
    	EntityStruc^ SoughtEntity;
    	EntityStruc^ ReturnEntity;
    
    	EntityTable->Clear();
    	EntityTable->Add(gcnew EntityStruc("Ball", "", ""));
    	EntityTable->Add(gcnew EntityStruc("Bat", "", ""));
    	EntityTable->Add(gcnew EntityStruc("Boy", "", ""));
    
    	SoughtEntity->Entity = "Boy";
    	ReturnEntity = EntityTable->Find(SoughtEntity);
    	}
    }
    

    Which throws the following compile error:

    error C2664: 'System::Collections::Generic::List<T>::Find' : cannot convert parameter 1 from 'EntityStruc ^' to 'System::Predicate<T> ^'

    I've also tried:

    ReturnEntity = EntityTable->Find(delegate(SoughtEntity){};)
    

    Which returns:

    error C3861: 'delegate': identifier not found

    As well as a plagerised C# version of:

    ReturnEntity = EntityTable->Find(delegate(SoughtEntity){
    	return SoughtEntity->Entity == "Boy";
    };)
    

    After acknowledging that I really don't know what I'm doing here I thought it best to ask for some assistance.

    1.  Does the Visual C++ language support the Find method on the List object?
    2.  If so, how would I do the above and a little explanation so I understand what's happening would be greatly appreciated.

     

    Sunday, November 14, 2010 10:23 AM

Answers

  • The Find method is supported but as the C# version shows it takes a delegate of type Predicate and not an instance of the object you're searching for.

    What C++/CLI does not support is "annonymous delegates" which is what the C# version of the code is using. To do this in C++/CLI you need a separate function: 

    bool IsBoy(SoughtEntity ^entity) {
     return entity->Entity == "Boy";
    }
    

    and then Find can be used like this:

    ReturnEntity = EntityTable->Find(gcnew Predicate<SoughtEntity>(IsBoy));
    
    Sunday, November 14, 2010 10:54 AM

All replies

  • The Find method is supported but as the C# version shows it takes a delegate of type Predicate and not an instance of the object you're searching for.

    What C++/CLI does not support is "annonymous delegates" which is what the C# version of the code is using. To do this in C++/CLI you need a separate function: 

    bool IsBoy(SoughtEntity ^entity) {
     return entity->Entity == "Boy";
    }
    

    and then Find can be used like this:

    ReturnEntity = EntityTable->Find(gcnew Predicate<SoughtEntity>(IsBoy));
    
    Sunday, November 14, 2010 10:54 AM
  • Thank you for that.  Much appreciated.  Another silly question leading off from that.  Obviously hard coding the search term is a bit limiting.  Can I do something like:

    bool FindSearchTerm(SoughtEntity ^entity, String ^SearchTerm) {
     return entity->Entity == SearchTerm;
    }
    

    And then call it something like:

    ReturnEntity = EntityTable->Find(gcnew Predicate<SoughtEntity>(FindSearchTerm("Boy")));
    

    Or would I have to declare the SeachTerm as a global variable, populate it and then call the comparison function?

    Sunday, November 14, 2010 11:16 AM
  • That doesn't work and using a global variable is better avoided. One option is this:
    value class EntityPredicate {
      String ^what;
    public:
      EntityPredicate(String ^term) {
        what = term;
      }
      bool IsMatch(SoughtEntity ^entity) {
        return entity->Entity == what;
      }
    }
    
    

    Used like this: 

    void foo() {
      EntityPredicate p("Boy");
      ReturnEntity = EntityTable->Find(gcnew Predicate<SoughtEntity>(p, &EntityPredicate::IsMatch));
    }
    
    
    Sunday, November 14, 2010 12:03 PM
  • Mike, thank you very for this.    It's going to take me at least two days to work through and make sure I understand what is happening with all of this but you've given a good steer in the right direction.

    Sunday, November 14, 2010 12:22 PM
  • Just so if anyone else is trying this this is what the final code looked like:

    public ref class EntityStruc{
    	public:
    		String^ Entity;
    		String^ System;
    		String^ Type;
    	public:
    		~EntityStruc(){
    		}
    		EntityStruc(String^ EntityIn, String^ SystemIn, String^ TypeIn){
    				this->Entity = EntityIn;
    				this->System = SystemIn;
    				this->Type = TypeIn;
    		}
    };
    private ref class EntityPredicate{
    	String^ SearchTerm;
    public:
    	EntityPredicate(String^ SearchTermIn){
    		SearchTerm = SearchTermIn;
    	}
    	bool Matched(EntityStruc^ CompareEntity){
    		return CompareEntity->Entity == SearchTerm;
    	}
    };
    EntityPredicate^ FindEntity;
    EntityStruc^ ReturnEntity;
    .
    .
    .
    .
    //If source isn't in EntityTable then add it
    FindEntity = gcnew EntityPredicate(Source);
    ReturnEntity = EntityTable->Find(gcnew Predicate<EntityStruc^>(FindEntity, &EntityPredicate::Matched));
    if(ReturnEntity == nullptr){
    	EntityTable->Add(gcnew EntityStruc(Source, System, ""));
    }
    Thanks again Mike.  All due to you.
    Sunday, November 14, 2010 1:03 PM
  • C# has strong support for these cool tricks. Await 'functions' are just wrapper classes for the
    .NET Wait() ...

    as/of keywords in C# are wrapper classes...

    See below for a C++/CLI implementation of Predicate<T^>and an effective emulation of the C# anonymous delegate. After seeing this, you will not want to spend almost any time using the .NET Predicate<T>in C++/CLI.
    Still, fun to see.

        .cpp file

    Star^ CppClasLibrary::TestPredicateByGenericList(Star^ searchStar)
    {
    	List<Star^>^ myList = gcnew List<Star^>();
    
    	for (int i = 0; i < 6; i++)
    	{
    		myList->Add(gcnew Star(L"My Star Name #" + i.ToString(), i+1, i*63));
    
    		if(i == 4)
    			myList->Add(gcnew Star(L"The Sun", 69, 433691.4107l));
    		}
    
    
    		m_starList = myList;
    
    		// Instantiate a 'PredicateDelegate'.
    		PredicateDelegate^ pd = gcnew PredicateDelegate(searchStar);
    
    		Star^ match = myList->Find(gcnew Predicate<Star^>(pd, &PredicateDelegate::MyFunction));
    
    		if (match == nullptr)
    			return gcnew Star(L"<<< Not Found >>>", pd->MyStar->ID);
    
    		return match;
    	}
    
    	bool PredicateDelegate::MyFunction(Star^ s)
    	{
    		return (this->MyStar->ID == s->ID);
    	}
       

        .h file

    public ref class Star
    	{
    	private:
    		String^ m_starname;
    		int m_code;
    		long long unsigned m_distance;
    
    	public:
    		const long long _1AU = 149597870700;		// 149,597,870,700 meters  (~93 million miles)
    
    	public:
    		Star() {}
    		Star(String^ starname, int code) : m_starname(starname), m_code(code) {}
    		Star(String^ starname, int code, long long distance) : m_starname(starname), m_code(code), m_distance(distance) {}
    		~Star() {}
    
    	public:
    		property long long Distance
    		{
    			long long get() { return m_distance; }
    			void set(long long value) { m_distance = value; }
    		}
    
    		property String^ StarName
    		{
    			String^ get() { return m_starname; }
    			void set(String^ value) { m_starname = value; }
    		}
    
    		property int ID
    		{
    			int get() { return m_code; }
    			void set(int value) { m_code = value; }
    		}
    	};
    
    
    	public ref class PredicateDelegate
    	{
    	private:
    		Star^ m_star;
    
    	public:
    		PredicateDelegate() {}
    		PredicateDelegate(Star^ s) : m_star(s) { }
    		~PredicateDelegate() {}
    
    		bool MyFunction(Star^ s);
    
    		property Star^ MyStar { Star^ get() { return m_star; } }
    	};
    
    
    	public ref class CppClasLibrary
    	{
    	private:
    
    	protected:
    		//delegate bool PredicateDelegate(Star^);
    
    	public:
    		CppClasLibrary();
    		CppClasLibrary(List<Object^>^ o);
    		~CppClasLibrary();
    
    		List<Star^>^ m_starList;
    		Star^ TestPredicateByGenericList(Star^ Daniel);
    		bool MyFunction(Star^ id);
    	};

    It would be fantastic to see WPF fully supported for C++ and C++/CX in future.

    }


    • Edited by DEV_Dan Tuesday, September 8, 2015 12:29 PM Formatting of html brackets instead of generics
    • Proposed as answer by DEV_Dan Tuesday, September 8, 2015 12:32 PM
    Tuesday, September 8, 2015 12:28 PM