class messageA {
};
class messageB {
};
template<class T>
class queue {
public:
virtual ~queue() {}
void submit(T& x) {}
};
class A : public queue<messageA>, public queue<messageB>
{
};
int main()
{
A aa;
aa.submit(messageA());
aa.submit(messageB());
}
My first thought is, the above code should be fine, as class A will contains 2 overloaded submit functions, which will accept messageA and messageB object.
However, the compiler gives me the following error :
May I know why there is an ambiguous? Isn't it is quite obvious that, for the 1st submit call, I want to call messageA version? For the 2nd submit call, I want to call messageB version?
------ Build started: Project: main, Configuration: Release Win32 ------
Compiling...
main.cpp
.\main.cpp(21) : error C2385: ambiguous access of 'submit'
could be the 'submit' in base 'queue<messageA>'
or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(21) : error C3861: 'submit': identifier not found
.\main.cpp(22) : error C2385: ambiguous access of 'submit'
could be the 'submit' in base 'queue<messageA>'
or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(22) : error C2664: 'queue<T>::submit' : cannot convert parameter 1 from 'messageB' to 'messageA &'
with
[
T=messageA
]
.\main.cpp(22) : error C3861: 'submit': identifier not found
I have no compiler right now, but I guess one inheritance could hide the other : The compiler will use Koenig Lookup to find the right symbol, and if I remember correctly, once the compiler find a suitable symbol (i.e., a method called "submit"), it will stop searching for others in parent and/or outer scopes.
In this case, I thought both inheriting classes would be searched for the symbol, but without your exact compiler (Visual C++ 2003 ? 2008 ? 2010 ?), I cannot guess much more.
After some thoughts, another possibility is that the compiler did find both symbols, but is unable to decide which to call (at that moment of symbol resolution, the compiler cares only for symbol name, not its exact prototype). I believe this last explanation to be the right one.
Try adding using statements in your derived classes :
class A : public queue<messageA>, public queue<messageB>
{
using queue<messageA>::submit ;
using queue<messageB>::submit ;
} ;
to bring both the submit methods directly in the A class scope.
Note, too, that your submit methods are taking messages as non-const reference, while in the constructor, your message parameters are temporaries (and thus, const r-values).
Re-writting the main as:
int main()
{
A aa;
messageA mA ;
messageA mB ;
aa.submit(mA);
aa.submit(mB);
}
could help compile (this could explain the compiler error on line 22).
Or you could change the prototype of your submit methods to accept const references instead of non-const references.
Note: Still without compiler, so trying to brain-debug your code... :-P ...
Something* smth1 = ((Base<Something> *)d)->createBase<Something>();
The above code works fine.
Related
I have a base class:
#define OUT
#define NO_VTABLE __declspec(novtable)
class NO_VTABLE Foo
{
public:
virtual bool TestSomething() const = 0;
virtual bool TestSomething(OUT unsigned int& extendedInfo) const {
UNUSED(extendedInfo);
return TestSomething();
}
};
And a derived class:
class NO_VTABLE Bar : public Foo
{
public:
virtual bool TestSomething() const {
// Do the test, return the result...
}
};
Under GCC, the program compiles cleanly with -Wall -Woverloaded-virtual. Under Visual Studio, I get a dirty compile. TestSomething from above is Available shown below.
1> ...\derived.h(78) : warning C4266: 'bool DeviceState::Available(unsigned int &) const' :
no override available for virtual member function from base 'DeviceState'; function is hidden
1> ...\base.h(794) : see declaration of 'DeviceState::Available'
1> ...\base.h(787) : see declaration of 'DeviceState'
Removing NO_VTABLE makes no difference. The warning persists.
All the TestSomething are public and virtual in both the base and derived classes, so its not clear to me what is hidden from the caller.
I'm working through testing under Visual Studio, and I've encountered it on both Visual Studio 2005, 2008 and 2010. I still have other VS's to test, but at this point, I know its not a one-off.
I prefer not to turn off the warning because the file base.h is large with lots of classes, and it might encounter other problems in the future.
What does Visual Studio claim is hidden from the caller? What is the source of the warning under Visual Studio, and how do I clear it?
If you look up error C4266 you'll find that it says A derived class did not override all overloads of a virtual function. So for this compiler you'll need to override all of the overloads for the unsigned int & variant to be visible.
I haven't looked up in the language spec to see if this is conforming or not.
I've asked a similiar question before but now I'd like to be more specific.
The problem I face is that I have an object that contains a non copyable object and when someone wants to use my interface and he does not use it well (does try to use the object's copy constructor) he will get a compilation error that will point to the object and not his actual code.
So two questions:
1. can I fix it somehow to point it to his original code line?
2. if I cannot, how can I put a static_assert that will only happen if someone actually tries to use the copy c'tor(I've tried a few but then I get them even if someone doesn't use it...)
I am adding a sample code and the compilation error in case I was not understood...
Notice the last compile error points to the ObjectHolder h. file.. while I want it to point to the main
Thanks!
* was a mistake when I replaced names.. it is in fact the code that created the compilation error.
and Let's assume I don't want to implement a private copy c'tor just to forward the disability to copy
class NonCopyableObject
{
public:
virtual ~NonCopyableObject () {}
NonCopyableObject(int i) { m_index = i;}
int m_index;
private:
NonCopyableObject(const NonCopyableObject& other) {}
};
class ObjectHolder
{
public:
virtual ~ObjectHolder ();
ObjectHolder(int i) : obj(i) {}
NonCopyableObject obj;
};
void main()
{
ObjectHolder first(1);
ObjectHolder second(first);
}
1>------ Build started: Project: tester, Configuration: Debug Win32 ------
1> main.cpp
1>d:\users\someone\documents\visual studio 2012\projects\tester\tester\objectholder.h(13): error C2248: 'NonCopyableObject::NonCopyableObject' : cannot access private member declared in class 'NonCopyableObject'
1> d:\users\someone\documents\visual studio 2012\projects\tester\tester\noncopyableobject.h(15) : see declaration of 'NonCopyableObject::NonCopyableObject'
1> d:\users\someone\documents\visual studio 2012\projects\tester\tester\noncopyableobject.h(8) : see declaration of 'NonCopyableObject'
1> This diagnostic occurred in the compiler generated function 'ObjectHolder::ObjectHolder(const ObjectHolder &)'
The error messages supplied do not reflect the code supplied.
That aside you have an error. Considering the code:
class ObjectHolder
{
public:
virtual ~ObjectHolder ();
ObjectHolder(int i) : obj(i) {}
ObjectHolder obj;
};
How is the compiler suppose to ascertain the amount of memory required for an ObjectHolder when it is recursive?
I have a problem compiling a c++ program with gcc version 4.6.3; I can compile this program with microsoft compiler (v 9.0) without problems.
This program is using some of my libraries I always used with microsoft compiler.
problem is when I try to pass a reference as argument that is a subtype of another: pseudo example here:
class ObjManager{..}
class SubObjMng : public ObjManager{
public:
inline SubObjMng() : ObjManager(0, ... ){}
};
class Test{
public:
Test(int i, ObjManager &obj_mng);
}
int main(){
SubObjMng myobjmng;
Test t(0, myobjmng); //GCC ERROR HERE
}
output of the error is (real output for my program):
globals.h:227:40: error: no matching function for call to cdk::HashMap::HashMap(unsigned int, cdk::PtrObjMng, cdk::cstrObjMng)
globals.h:227:40: note: candidates are:
contrib/cdklib/cdk_struct.h:485:12: note: cdk::HashMap::HashMap(uint32_t, cdk::ObjManager&, cdk::ObjManager&)
contrib/cdklib/cdk_struct.h:485:12: note: no known conversion for argument 2 from cdk::PtrObjMng to cdk::ObjManager&
anyone can help?
thanks!
cdk::PtrObjMng should inherit from cdk::ObjMng, making polymorphism possible through references. Otherwise this is a no-go according to what the compiler says.
Of course this might not be the root of your problem, I wish we could see the implementation of your constructor.
I was implementing boost::intrusive for one of my project on visual C++ 2008 and i stumbled upon a problem. i am using splay hooks for splay_multiset containers. I have defined splay hook publically under MyClass (code below).
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <iostream>
using namespace boost::intrusive;
class MyClass
{
int int_;
public:
MyClass(int i)
: int_(i)
{}
splay_set_member_hook<link_mode<normal_link> > memberSplayHook;
//**OPTION-1**
//PROBLEM CODE SEGMENT ++
//typedef member_hook<MyClass, splay_set_member_hook<link_mode<normal_link> >, &MyClass::memberSplayHook> MemberOption;
//typedef splay_multiset<MyClass, MemberOption> MemberMultiSet;
//PROBLEM CODE SEGMENT --
MemberMultiSet mmset;
};
//**OPTION-2**
//WORKING CODE SEGMENT ++
typedef member_hook<MyClass, splay_set_member_hook<link_mode<normal_link> >, &MyClass::memberSplayHook> MemberOption;
typedef splay_multiset<MyClass, MemberOption> MemberMultiSet;
//WORKING CODE SEGMENT --
int main()
{
return 0;
}
The problem is, to use splay_multiset, whatever option i choose (either option-1 or 2, mention in code), in both cases i see compilation errors.
When Option-1 is enabled (option-2 is commented), i see errors below:
1>d:\projects\sampleproject\sample.cpp(21) : error C2327: 'MyClass::memberSplayHook' : is not a type name, static, or enumerator
1>d:\projects\sampleproject\sample.cpp(21) : error C2065: 'memberSplayHook' : undeclared identifier
1>d:\projects\sampleproject\sample.cpp(22) : error C3203: 'member_hook' : unspecialized class template can't be used as a template argument for template parameter 'O1', expected a real type
While, when Option-2 is enabled (option-1 is commented out), i dont see undeclared identifier error msg as these errors coming with option-1. But i do see errors like below (which are obvious).
1>d:\projects\sampleproject\sample.cpp(25) : error C2146: syntax error : missing ';' before identifier 'mmset'
1>d:\projects\sampleproject\sample.cpp(25) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
My question is why i am getting error in first case? What can i do to get pass this issue?
Boost member hooks have (always?) been broken, since they don't compile with Visual C++.
I don't have a VS at hand to check for the precise error message so I might be wrong (but reading 'member hooks' and 'Visual C++' always triggers 'there's a problem'-mode), but do try to check this:
http://permalink.gmane.org/gmane.comp.lib.boost.user/56875
EDIT: Don't take the headline literally -- the same applies to Visual C++ 2010 and 2012. All my member hooks use this workaround; at some point I might even try to understand what it does, or more importantly, how to package it into a more comfortable setup for less "I need to find a previous implementation of this workaround so I can copy-and-modify it"...
I am trying to compile a file which defines a garbage collection template and several supporting classes with use of operator overloading. I've tried to run this through MSVC++ 2008, and the compile stops at this particular class:
// (The collector defines gc_object_generic_base which
// inherits from gc_object_generic_base and optionally adds
// collector-specific properties.)
template<class garbage_collector>
class gc_object_base : public garbage_collector::gc_object_collector_base {
public:
gc_object_base() {
garbage_collector::constructing_gc_object_base(this);
}
static void* operator new(size_t sz,
block_construction_locker_base* lock = block_construction_locker<garbage_collector>().get_this())
{
return garbage_collector::allocate(sz, lock);
}
static void operator delete(void* p, block_construction_locker_base* lock) {
return garbage_collector::deallocate(p);
}
static void operator delete(void* p) {
return garbage_collector::deallocate(p);
}
private:
// TODO: are arrays worth implementing?
static void* operator new[](size_t sz) {
assert(0);
return 0;
}
};
Truncated output for brevity's sake:
2>------ Build started: Project: Test, Configuration: Debug Win32 ------
2>Compiling...
2>FlashTest.cc
2>C:\test\gameswf\base\tu_gc.h(133) : error C2059: syntax error : 'string'
2> C:\test\gameswf\base\tu_gc.h(151) : see reference to class template instantiation 'tu_gc::gc_object_base' being compiled
2>C:\test\gameswf\base\tu_gc.h(135) : error C2091: function returns function
2>C:\test\gameswf\base\tu_gc.h(135) : error C2802: static member 'operator new' has no formal parameters
2>C:\test\gameswf\base\tu_gc.h(135) : error C2333: 'tu_gc::gc_object_base::operator new' : error in function declaration; skipping function body
Any ideas on where I should start looking at?
I just had the same pattern of errors in a different project. It seems to happen when someone has done this somewhere:
#define new new(someArgs, someMoreArgs, etc)
It's targeted at simple 'new' expressions, but it breaks down if anyone tries to declare any more 'operator new' thingies.
In the opening lines
template<class garbage_collector>
class gc_object_base : public garbage_collector::gc_object_collector_base {
garbage_collector appears twice here, once as the template parameter and another as an outer-class to gc_object_collector_base, but as it is a template parameter does it not require "typename" here thus:
template<class garbage_collector>
class gc_object_base : public typename garbage_collector::gc_object_collector_base {
There is no mention of string in your code, that I can see. But I would start by ensuring that you first #include <string> before your class delcaration, and then make sure you use std::string as your declarator, rather than just string.