cannot convert from Icollection to Icollection c /cli - c++-cli

i need to fill a collection with another list in c++/cli so the problem that when i try to do that i got an error
error C2664: 'SpaceClaim::Api::V10::InteractionContext::Selection::set' : cannot convert parameter 1 from 'System::Collections::Generic::ICollection ^' to 'System::Collections::Generic::ICollection ^'
and here the code
List<DesignEdge^> ^newEdges = gcnew List<DesignEdge^>();
for each (DesignEdge^edge in onecopiedBody->Edges)
{
if (!edges->Contains(edge))
{
newEdges->Add(edge);
}
}
cstom->InteractionContext->Selection = safe_cast<ICollection<IDesignEdge^> ^>(newEdges); //error here

The problem is that you're trying to cast from ICollection<DesignEdge^>^ to ICollection<IDesignEdge^>^, which is not safe. What you should do is operate in terms of IDesignEdge from the start:
auto newEdges = gcnew List<IDesignEdge^>();

Related

Is g++ 4.5.3 broken when it comes to pointers to lamba functions?

I was trying out lambda functions and making a jump table to execute them, but I found g++ didn't recognize the type of the lambda function such that I could assign them to an array or tuple container.
One such attempt was this:
auto x = [](){};
decltype(x) fn = [](){};
decltype(x) jmpTable[] = { [](){}, [](){} };
On compilation I get these errors:
tst.cpp:53:27: error: conversion from ‘main()::<lambda()>’ to non-scalar type ‘main()::<lambda()>’ requested
tst.cpp:54:39: error: conversion from ‘main()::<lambda()>’ to non-scalar type ‘main()::<lambda()>’ requested
Hmmmm, can't convert from type A to non-scalar type A? What's that mean? o.O
I can use std::function to get this to work, but a problem with that is it doesn't seem to work with tuple:
function<void()> jmpTable[] = [](){}; // works
struct { int i; function<void()>> fn; } myTuple = {1, [](){}}; // works
tuple<int, function<void()>> stdTuple1 = {1, [](){}}; // fails
tuple<int, function<void()>> stdTuple2 = make_tuple(1, [](){}); // works
tst.cpp:43:58: error: converting to ‘std::tuple<int, std::function<void()> >’ from initializer list would use explicit constructor ‘std::tuple<_T1, _T2>::tuple(_U1&&, _U2&&) [with _U1 = int, _U2 = main()::<lambda()>, _T1 = int, _T2 = std::function<void()>]’
Constructor marked explicit? Why?
So my question is if I am doing something invalid or is this version just not quite up to the task?
Hmmmm, can't convert from type A to non-scalar type A? What's that mean? o.O
No, that's not a conversion to the same type. Despite having identical bodies, the different lambdas have different types. Newer versions of GCC make this clearer, and give the error message:
error: conversion from '__lambda1' to non-scalar type '__lambda0' requested
clang does even better:
error: no viable conversion from '<lambda at test.cc:2:18>' to 'decltype(x)' (aka '<lambda at test.cc:1:10>')
I can use std::function to get this to work, but a problem with that is it doesn't seem to work with tuple:
It does (with 4.5.4, at least, I don't have 4.5.3 to test), but your initialisation isn't quite right.
tuple<int, function<void()>> stdTuple1 {1, [](){}}; // lose the = to initialise stdTuple1 directly
I'm not sure about the state of n3043 in 4.5.3, but you should be able to use function pointer conversion. If I'm not misunderstanding your usage intentions, this may work for you;
void (*x)();
decltype(x) fn = [](){};
decltype(x) jmpTable[] = { [](){}, [](){} };

Listing WIA devices in C++/CLI fails with "cannot convert from 'int' to 'System::Object ^%'"

I'm trying to list all WIA devices with C++/CLI. I'm fairly new to C++/CLI (although I consider myself an intermediate C++ programmer), but I keep getting this error:
error C2664: 'WIA::IDeviceInfos::default::get' : cannot convert parameter 1 from 'int' to 'System::Object ^%'
when using the following code snippet:
DeviceManager^ dm = (gcnew WIA::DeviceManager());
for (int i = 1; i <= dm->DeviceInfos->Count; i++)
{
String^ deviceName = dm->DeviceInfos[i].Properties("Name")->get_Value()->ToString();
this->devices->Items->Add(deviceName);
}
Why should I treat that int as an Object? In Managed C++ there was the concept of boxing, but it doesn't work here and anyway I thought C++/CLI was introduced in order to get rid of it?
The Value property needs some non-obvious code to get it out. Try this:
WIA::DeviceInfo ^ info = dm->DeviceInfos[gcnew System::Int32(i)];
WIA::Property ^ propName = info->Properties[gcnew System::String(L"Name")];
String ^ strName = propName->default->ToString();

c++/cli Dictionary within a function argument

I am getting familiar with c++/cli. I am writing a function called Locate with a class called Locator. The function that takes input a dictionary of strings.
Dictionary<String^, array< Byte >^>^ Locate(Dictionary<String^, String^>^ imgParms)
I am trying to call it in the main function by doing this:
Locator r;
Dictionary<String^,String^> myDictionary =
gcnew Dictionary<String^,String^>();
r.Locate(myDictionary);
but I am getting this error
error C3073: 'System::Collections::Generic::Dictionary<TKey,TValue>' : ref class does
not have a user-defined copy constructor with
[
TKey=System::String ^,
TValue=System::String ^
]
Any help would be appreciated.
Dictionary<String^,String^> myDictionary =
gcnew Dictionary<String^,String^>();
Should be
Dictionary<String^,String^>^ myDictionary =
gcnew Dictionary<String^,String^>();
the ^ symbol can be thought of as a type modifier like * do gcnew is returning you ax^ to type x

System::Object to int or double in C++/CLI

I'm taking some information from data base and i want to use it in calculations. But due to what i'written, i'm not able to convert it to number. I recieve System::Object^. here is the part of code:
OleDbConnection ^ cnNwind = gcnew OleDbConnection();
cnNwind-> ConnectionString =
L"Provider = Microsoft.Jet.OLEDB.4.0;"
L"Data Source = C:\\temp\\A.mdb";
try
{
// Open the database
cnNwind->Open();
Console::WriteLine(L"Connected to database successfully!");
// Count the customers
OleDbCommand ^ cmProducts = gcnew OleDbCommand();
cmProducts->CommandText = L"SELECT ID FROM Table1";
cmProducts->CommandType = CommandType::Text;
cmProducts->Connection = cnNwind;
// Print the result
Object ^ numberOfProducts = cmProducts->ExecuteScalar();
Console::Write(L"Number of products: ");
Console::WriteLine(numberOfProducts);
}
catch (OleDbException ^ pe)
{
Console::Write(L"Error occurred: ");
Console::WriteLine(pe->Message);
}
// Close the connection
if (cnNwind->State != ConnectionState::Closed)
{
cnNwind->Close();
}
Console::WriteLine(L"The database connection is closed...");
I want to use numberOfProducts as a digit. I mean type double or integer. How can i transform it?
Simply use safe_cast to cast the Object^ to the appropriate type. This is covered in detail on this page: How to: Use safe_cast in C++/CLI
Object^ numberOfProductsObj = cmProducts->ExecuteScalar();
// IIF the underlying type is System::Int32
int numberOfProducts = safe_cast<int>(numberOfProductsObj);
// or, IIF the underlying type is System::Double
double numberOfProducts = safe_cast<double>(numberOfProductsObj);
Since there can only be one underlying type (and I don't know what it is in your case), only one of these will work -- the other will throw an exception. Point being, your first step is to determine the actual underlying type (presumably double, float, or int).

...array<Object^>^ args

I'm reading C++/CLI. I see this stuff:
Object^ CreateInstanceFromTypename(String^ type, ...array<Object^>^ args)
{
if (!type)
throw gcnew ArgumentNullException("type");
Type^ t = Type::GetType(type);
if (!t)
throw gcnew ArgumentException("Invalid type name");
Object^ obj = Activator::CreateInstance(t, args);
return obj;
}
When calling it:
Object^ o = CreateInstanceFromTypename(
"System.Uri, System, Version=2.0.0.0, "
"Culture=neutral, PublicKeyToken=b77a5c561934e089",
"http://www.heege.net"
);
What is ...array^ args? If I remove ... ,there's a complied-error:
error C2665: 'CreateInstanceFromTypeName' : none of the 2 overloads could convert all the argument types
1> .\myFourthCPlus.cpp(12): could be 'System::Object ^CreateInstanceFromTypeName(System::String ^,cli::array<Type> ^)'
1> with
1> [
1> Type=System::Object ^
1> ]
1> while trying to match the argument list '(const char [86], const char [21])'
Like C++, C++/CLI has a mechanism for a variable amount of arguments. That is what the ... in front of the ...array<Object^>^ parameter means.
For type safety the C++/CLI designers added managed syntax to declare the type of the variable array.
Since it's just passing that parameter to the Activator::CreateInstance() function, I would look at what variable parameters the Activator function is looking for.