ambiguous copy constructors vc 2008 - visual-c++

I'm trying to recompile older code in latest Visual Studio (2008) and code that worked previously now fails to compile. One of the problems is due to overloaded operators for my class. below there is simplified class to demonstrate the problem. If I remove casting operators for int and char* then it works fine. So one of the ways to fix my issue is to replace them with procedures to_char and to_int and use them instead but it will require a lot of changes in the code (that class is heavily used). There must be some better, smarter way to fix it. any help is greatly appreciated :-)
class test
{
public:
test();
test(char* s2);
test(int num);
test(test &source);
~test();
operator char*();
operator int();
};
test::test() {
}
test::test(char* s2) {
}
test::test(int num) {
}
test::test(test &source) {
}
test::operator char*() {
}
test::operator int() {
}
test test_proc() {
test aa;
return aa;
}
int test_proc2(test aa)
{
return 0;
}
int main()
{
test_proc2(test_proc());
}
//test.cpp(60) : error C2664: 'test_proc2' : cannot convert parameter 1 from 'test' to 'test'
// Cannot copy construct class 'test' due to ambiguous copy constructors or no available copy constructor

Try changing
test(test &source);
to
test(const test &source);
The issue is that the test_proc call returns a temporary test object, which can be passed to a function that accepts a const reference, but not a plain reference.

Related

Offsetof alternative for modern C++

I'm trying to add a map to my datatype that maps member name strings to the local offset of the member variable like this:
struct E
{
B memberX;
B memberY;
constexpr static entry map[] = {
{ "memberX", offsetof( E, memberX ) },
{ "memberY", offsetof( E, memberY) }
};
};
This doesn't compile with VS2015. If fails at { "memberX", offsetof( E, memberX ) }, with error C2227.
Besides, I know that offsetof doesn't work reliably for non pod types.
Do you have a suggestion how to do what I want in a compatible, modern way?
Thanks!
Not that this way is modern, but offsetof is often defined as following:
#define offsetof(type, memb) (intptr_t)&(((type)NULL)->memb)
so you can try using that as alternative.
I am assuming that you want to use the offsets only to access the members later. In that case and given that all members have the same type, a pointer-to-data-member is probably safer and more general:
struct E
{
B memberX;
B memberY;
static const auto& getMemberMap {
static const std::map<std::string, B E::*> memberMap {
{ "memberX", &E::memberX },
{ "memberY", &E::memberY }
};
return memberMap;
};
B& getMember(const std::string& str) {
auto it = getMemberMap().find(str);
if(it == getMemberMap().end()) {
// throw some exception
}
return this->*(it->second);
};
};
std::map does not have a constexpr constructor, so the map will be built runtime rather than compile-time, but you can replace it with your own implementation.
I used a local static variable instead of a static member because you required the initializiation to be contained in the class definition.

Why is the struct unknown at compiletime in the code?

I was wondering how I could change the code below such the bmBc is computed at compile time . The one below works for runtime but it is not ideal since I need to know the bmBc table at compile-time . I could appreciate advice on how I could improve on this.
import std.conv:to;
import std.stdio;
int [string] bmBc;
immutable string pattern = "GCAGAGAG";
const int size = to!int(pattern.length);
struct king {
void calculatebmBc(int i)()
{
static if ( i < size -1 )
bmBc[to!string(pattern[i])]=to!int(size-i-1);
// bmBc[pattern[i]] ~= i-1;
calculatebmBc!(i+1)();
}
void calculatebmBc(int i: size-1)() {
}
}
void main(){
king myKing;
const int start = 0;
myKing.calculatebmBc!(start)();
//1. enum bmBcTable = bmBc;
}
The variables bmBc and bmh can't be read at compile time because you define them as regular runtime variables.
You need to define them as enums, or possibly immutable, to read them at compile time, but that also means that you cannot modify them after initialization. You need to refactor your code to return values instead of using out parameters.
Alternatively, you can initialize them at runtime inside of a module constructor.

how to pass a reference to const pointer correctly?

I just wonder how I can efficiently pass a reference to const pointer to an object of a class.
For example,
class BigData
{
public:
int m[1000];
};
void Func(const BigData* const& bigData)
{
// just read bigData; No modification on bigData.
}
int main()
{
BigData* bigData = new BigData();
Func(bigData);
}
Above example, I do not quite understand why I have to put const before reference(&).
If I try to build it without the reference, the compiler complains about
cannot convert parameter 1 from 'BigData *' to 'const BigData *&'
Seems like it is related to R-value rule but I don't know what rule exactly governs this case.
TIA
}
Don't. Just pass the pointer by value. Syntactically it is easier for the called function to use, and will have less overhead.
void Func(const BigData *bigData)

Why doesn't this C# code compile when using named parameters?

Baffled.
class Test
{
void Main()
{
F(() => ""); // ok
F(named: () => ""); // 'T' cannot be inferred from the usage!
F<string>(() => ""); // ok
F<string>(named: () => ""); // ok
}
void F<T>(Func<T> named) { }
}
Could someone tell me why the second call to F fails to compile?
(Note that this is a significantly stripped down example, which is why it seems synthetic. In the real case I came across, there are some default parameters before 'named' and so the named parameter is required. And so, apparently is explicit specification of 'T' by the caller.)
Seems like an inadequacy in the compiler's delegate type inference...sorry I can't offer more.

Is move by lvalue broken/unfinished in msvc2010?

I dont know why this code doesnt work. this_ is shown as 0xcccccccc and v is no longer 4. Why?
Note: I am trying to use the lvalue/move semantics.
struct AA{
void*this_;
int v;
AA() {v=4;this_=this; }
AA(AA&a){this_=this; }
AA(AA&&a){
this_=a.this_;
v = a.v;
}
};
void movetest(AA s) {}
void movetest(AA& s) {}
//void movetest(AA&& s) {}
AA&& movetest() { return AA(); }
void MyTestCode2(){
AA c = movetest();
printf("wron value. 4 !='%d'\n", c.v);
}
That's returning a reference to a local. It should be
AA movetest() { return AA(); }
This code requires either a move or copy constructor to exist, but MSVC will use the return-value-optimization and not actually call either. In general, you should design your objects as if moves or copies happen outside your control--just maintain consistent state of your object, don't rely on their side-effects.
VC2010 is correctly preferring move to copy, for example on a debug build
AA movetest()
{
AA a;
return a;
}
calls the AA(AA&&) constructor not the AA(AA&) one.
Extra info: This is an answer instead of a comment only because of formatting concerns.
A warning would be nice, but is not required by the language. Try returning a local lvalue by AA& and see if you get a warning.
clang++ gives the following warning for your code:
test.cpp:14:26: warning: returning reference to local temporary object
AA&& movetest() { return AA(); }
^~~~

Resources