Calling a property on the const reference - windows

I have C++/CLI class that defines a property:
public ref class AbstractOffer
{
public:
AbstractOffer();
property String^ Body;
};
In some function the AbstractOffer class is passed by const ref
foo(const AbstractOffer^ ao)
{
ao->Body;
}
When I call the property the method compiler gives the following error :-
error C2662: 'ivrworx::interop::AbstractOffer::Body::get' : cannot
convert 'this' pointer from 'const ivrworx::interop::AbstractOffer'
to 'ivrworx::interop::AbstractOffer %' 1> Conversion loses
qualifiers
It seems somehow connected to const. How can I call the Body property of the object if the object reference is passed by const?

The const qualifier is a problem in C++/CLI. It is only meaningful when it can be checked and that's not in general possible in .NET. It is of course not a problem when you only have one kind of compiler and that compiler follows strict language rules. Like C++. But .NET supports many languages, your method could be easily called from a Cobol.NET program for example. The odds of ever getting const-correctness added to the Cobol language are zero.
The compiler does compile code with const qualifiers and does make an effort to check when it can. Which is why you got the diagnostic. That can even work when the declaration exists in another assembly, as long as it was compiled with C++/CLI, the compiler emits modopt annotations in the metadata.
But there are limitations with that. Properties are one of them, you can't add the const qualifier to the getter, or a member function in general, you'll get slapped with C3842.
Best thing to do is to use C++/CLI for what it is good at, it is an interop language. And const qualifiers just don't work well in an interop scenario.

The only way I know to get round this is the cast away the const-ness. As long as you don't modify the object, it should be fine. (If you do modify it, I've no idea what the outcome will be).
i.e. change your function to be
void foo(const AbstractOffer^ ao)
{
const_cast<AbstractOffer^>(ao)->Body;
}

Related

What is the best type for a callable object in a template method?

Every time I write a signature that accepts a templated callable, I always wonder what the best type for the parameter is. Should it be a value type or a const reference type?
For example,
template <class Func>
void execute_func(Func func) {
/* ... */
}
// vs.
template <class Func>
void execute_func(const Func& func) {
/* ... */
}
Is there any situation where the callable is greater than 64bits (aka a pointer to func)? Maybe std::function behaves differently?
In general, I do not like passing callable objects by const reference, because it is not that flexible (e.g. it cannot be used on mutable lambdas). I suggest to pass them by value. If you check the stl algorithms implementation, (e.g. for std::for_each), all of the callable objects are passed by value as well.
Doing this, the users are still able to use std::ref(func) or std::cref(func) to avoid unnecessary copying of the callable object (using reference_wrapper), if desired.
Is there any situation where the callable is greater than 64bits
From my experience in working in CAD/CAE applications, a lot. Functors can easily hold data that is bigger than 64 bits. More than two ints, more than one double, more than one pointer, is all you need to exceed that limit in Visual Studio.
There is no best type. What if you have noncopyable functor? First template will not work as it will try to use deleted copy constructor. You have to move it but then you will loose (probably) ownership of the object. It all depends on intended use. And yes, std::function can be much bigger than size_t. If you bind member function, it already is 2 words (object pointer and function pointer). If you bind some arguments it may grow further. The same goes with lambda, every captured value is stored in lambda which is basically a functor in this case. Const reference will not work if your callable has non const operator. Neither of them will be perfect for all uses. Sometimes the best option is to provide a few different versions so you can handle all cases, SFINAE is your friend here.

C++: What is semantics of std::function constness?

Reference says that std::function::operator() is const. What this constness applies to? If std::function is a wrapper around callable object, does constness applies to this object (meaning its operator() should be const too?).
Overall, what does it mean for std::function to be const for different kinds of targets (lambda, function pointer, object, member function, etc)?
It is a bug. Nothing is actually const as the target object is called from a non-const reference, per the specification.
A future revision of the standard library will remove const from the call operator. Users will be able to specifically request a properly const call using specializations such as std::function<return_type(arg_type) const>.
See standard proposal P0045. (Disclosure: I'm the author.)

Is it valid to return a unique_ptr pointing to a forward declared class?

Following code does not compile with clang-700.1.81 and it's standard library:
#include <memory>
class something;
std::unique_ptr<something> external_function();
std::unique_ptr<something> local_function()
{
auto thing = external_function();
return thing;
}
The diagnostics by clang:
......./include/c++/v1/memory:2626:46: note: in instantiation of member function 'std::__1::unique_ptr.....requested here
_LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
^
test.cc:10:18: note: in instantiation of member function 'std::__1::unique_ptr<something, std::__1::default_delete<something> >::~unique_ptr' requested here
auto thing = external_function();
^
test.cc:4:7: note: forward declaration of 'something'
class something;
^
I guess it is trying to destroy the unique_ptr after copying it as return value, but is this really necessary? It is going be moved anyways, does it need to check if it can copy before realizing that it is easier to move it?
I could of course do this easily with a naked pointer.
Is there some other way to allow a uniqe_ptr to just "pass through" a translation unit, as shown in the example, without including extra header to get the definition of class something?
------EDIT--------
Also tried with GCC 5.3.0 and gnu libstdc++
Does not compile as well, with similar error messages.
------EDIT----
I think it is just trying to destroy the original thing object.
Thanks to Rudolf for the deleter idea ( a bit messy, but only option for this )
Looking at the library code I found this in unique_ptr's code:
if (__tmp)
__ptr_.second()(__tmp);
where second(_tmp) destructs the object pointed to. Even though it is never called, the compiler needs a definition to compile it. This is silly, but apparently gotta live with it.
From cppreference.com:
std::unique_ptr may be constructed for an incomplete type T, such as to facilitate the use as a handle in the Pimpl idiom. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr. (Conversely, std::shared_ptr can't be constructed from a raw pointer to incomplete type, but can be destroyed where T is incomplete).
Thus, with a custom deleter you can use a forward declared class if the full declaration is available for the deleter:
#include <memory>
class Foo;
class FooDeleter
{
public:
void operator()(Foo* pInstance);
};
std::unique_ptr<Foo, FooDeleter> pFoo;
class Foo
{
};
void FooDeleter::operator()(Foo* pInstance)
{
delete pInstance;
}

SmartPointer from DLL: where to construct & destruct

I'm currently remodelling a dynamic library project and removed a lot of STL and other dependencies from its header resulting in conflicting implementations between different toolchains.
The DLL Interface now only contains plain C-types and custom types whom implementation depends solely on the DLL code. But now I'm stuck with two remaining points.
The DLL should return some sort of reference counting smart pointer (with a weak pointer option)
Managing construction and destruction between the DLL boundaries. This more or less looks like this.
.
#include <memory>
class Config;
typedef std::shared_ptr<Config> ConfigPtr;
class CONFIGAPI_DLL Config
{
public:
///...
ConfigPtr getNewNode( char const* query = "." )
{
// construct obj in dll, but construct shared_ptr in header
return ConfigPtr( _constructgetNewNode(query) );
}
ConfigPtr getNewNodeFromHeader( char const* query = "." )
{
// construct obj and shared_ptr in header
auto obj = new Config;
obj->_init(query);
return ConfigPtr( obj );
}
private:
Config* _constructNewNode( char const* query = "." );
void _init( char const* query = "." );
};
I was thinking by creating the share_ptr at the dll headers (getNewNode) it would prevent mixed implementations of std::shared_ptr ...but I don't know if that is a good idea?
But I also construct the new object inside the DLL (_constructNewNode) and this means it should also be destructed there?
I tried to construct it in the headers and so in the user code scope (getNewNodeFromHeader)... this shouldn't cause problems?
The downside is I still export the C++11 header and rule out all older compilers. Is it possible to export the shared_ptr type from the dll as unconflicting code but still be compatible with std::shared_ptr?
thanks!
I suppose you want to mix creation and destruction of the objects (Config and the shared_ptr). If the DLL client is not compiled with the same version and configuration of the compiler you would be in troubles (for example, mixing debug and release modules). The main problem I see here: there is not any type of standard ABI for C++.
I was thinking by creating the share_ptr at the dll headers
(getNewNode) it would prevent mixed implementations of std::shared_ptr
...but I don't know if that is a good idea?
If you define your header file to create the shared_ptr, that would be OK if only a module use that header file. I mean, if the shared_ptr is not to be used for the content of the DLL, for example. BUT if other client module (a binary module, like other DLL) use also that header, you must be sure they are compiled with the same compiler and compiling configuration. If you have not that guarantee, then is not good idea.
But I also construct the new object inside the DLL (_constructNewNode)
and this means it should also be destructed there?
If you construct the object inside the DLL, you'll be better destroying inside the DLL. How to do that? specifying a deleter at shared_ptr construction. Something like
struct ConfigDeleter {
void operator()(Config* c) {
c->destroy(); // or as you want to implement it.
};
typedef std::shared_ptr<Config, ConfigDeleter> ConfigPtr;
I tried to construct it in the headers and so in the user code scope
(getNewNodeFromHeader)... this shouldn't cause problems?
As before, it depends if you can guarantee all modules are homogeneous (same compiler version and configuration, library, etc.). But of you want to implement as that, do it well:
// construct obj and shared_ptr in header
auto obj_ = make_shared<Config>();
obj_->init(query);
It is exception-safe and more efficient: just one allocation to store the object and the reference, instead two allocations in your sample.
If you want your code be safe for mixing modules, implement all allocations (shared_ptr included) into the DLL, if they are shared. Exports a "C" interface, and create header file to wrap that interface in classes. Something like:
class WConfig {
public:
WConfig(): m(IDll->create()) {
}
// other member functions as interface stub
~WConfig() {
IDll->release(m);
}
private:
Config* m;
};
To share this object, you can use copy constructor (that copy the pointer and call to IDll->reference(m), for example) or any other approach.

Using an enum from a type library in VBScript

I'm implementing a COM interface for an existing application written in C++. The COM interface is used for automating the application from VBScript.
One of the methods I want to call via th COM interface has a parameter that, in C++, has an enum type. I have defined a corresponding enum type in the IDL file, and oleview shows the values are registered:
// Copied from type library viewer
typedef enum
{
MyValueA = 0,
MyValueB = 1,
MyValueC = 2
} MyEnum;
However, when I pass one of these values in VBScript, the value received by the CPP implementation is always 0. I assume I'm not using the correct VBScript syntax. Passing an integer value directly works, and passing something random (like ghfitgr) also results in 0, which is probably what is happening to MyValueB, etc.
I found a claim that enum.member should be used, which would be MyEnum.MyValue, but that results in a syntax error (object required: MyEnum). What am I doing wrong?
Late-bindng VBScript can't/won't pluck those info from the .dll, all you get are objects (by CreateObject()) and what they provide. So spare yourself a lot of hassle & hacks by defining the values with decent names using Const.
To clarify:
I meant: Const in the VBScript code.

Resources