I'm trying to work around the limitation that the default ctor of a custom Qt meta type has to be public by declaring certain functions as friends.
#include <QMetaType>
class QVariant;
template<typename T> inline T qvariant_cast(const QVariant &); // from qvariant.h
namespace foo
{
class Bar
{
private:
Bar(){};
friend void *::qMetaTypeConstructHelper<Bar>(const Bar *t); // works
friend inline Bar ::qvariant_cast<Bar>(const ::QVariant &v); // error C4430: missing type specifier
};
} // namespace foo
Q_DECLARE_METATYPE(foo::Bar)
void main()
{
QVariant v;
v.value<foo::Bar>();
}
When commenting out the marked line, I get the following error, which is expected:
1>[...]\qvariant.h(577): error C2248: 'foo::Bar::Bar' : cannot access private member declared in class 'foo::Bar'
But declaring the function as a friend doesn't work:
Bar.cpp(13): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
It almost seems like MSVC 2010 doesn't see the space between the "Bar" and the "::".
Aside from making the default ctor public, how can I get it to compile?
It almost seems like MSVC 2010 doesn't see the space between the "Bar" and the "::".
Spaces don't matter around :: meaning foo::bar is the same as foo ::bar.
Try adding parenthesis around the function name:
friend inline Bar (::qvariant_cast<Bar>)(const ::QVariant &v);
Related
I have a templated class:
template <typename vtype>
class BNode
{
public:
BNode::BNode(std::vector<BPoly<vtype>>& thePolys) {if(thePolys.size()) Build(thePolys);}
BNode::BNode() {}
BPlane* mPlane=nullptr;
//And more stuff
};
When I compile, I get this error on the BPlane* mPlane=nullptr line:
error C2146: syntax error: missing ';' before identifier 'BPlane'
(Using Visual Studio 2019 compiler)
Why do I need a semicolon after my {}? If I put the semicolon there, it works. But I'm curious what the problem is because I'm worried there's some issue that will bite me later.
The following code compile without any error:
#include <vector>
class BPlane;
template <class T> class BPoly { int i; };
template <typename vtype>
class BNode
{
public:
BNode(std::vector<BPoly<vtype>> &thePolys) { if (thePolys.size()) Build(thePolys); }
BNode() {}
BPlane *mPlane = nullptr;
void Build(...) {}
//And more stuff
};
int main()
{
BNode<char> s;
}
Thus, it is impossible to guess what you have done wrong as after writing simple types for missing declaration and including vector the code compile without adding any ; after a constructor.
And I have made an instantiation in main to be sure that the class is used.
I thought the new using syntax in C++11 and typedef were equivalent (except for templates). But it seems that with using it is also not possible to declare a class member.
class A {
//... Public members
private:
typedef std::vector<double> vector_double;
using vector_int = std::vector<int>;
void bar(vector_double& vecDouble); // type can be used
void foo(vector_int& vecInt); // type can't be used: synatx error
// ... Possible other private members
}
When I try to use the type vector_int in one of the member functions of class A I get a compiler error: syntax error: identifier 'vector_int'.
Am I doing something wrong here or is defining a member type not possible with using?
I have just started with C++ Qt and I wrote the following .h file: The .cpp file contains only empty constructors and destructors.
#include <QList>
class XML_Files
{
public:
XML_Files();
~XML_Files();
protected:
QList<Myclass> m_Xmls;
};
class Myclass
{
public:
Myclass();
~Myclass();
protected:
int a;
};
but I keep getting the following errors:
error C2065: 'Myclass': undeclared identifier
error C2923: 'QList': 'Myclass' is not a valid template type argument for parameter 'T'
What do I have to do to declare a Qlist with my own data type?
You can't use the name MyClass until the compiler knows about it. Since you do not declare MyClass until after XML_Files you cannot use it's name in XML_Files.
The simplest solution here is to just change the order of the declarations and declare MyClass before XML_Files.
The easy way to fix this, is to turn the order of both classes. However there is a second solution, if this is not desired or possible:
You may declare Myclass before defining it. Then compilation will succeed.
#include <QList>
class Myclass;
class XML_Files
{
public:
XML_Files();
~XML_Files();
protected:
QList<Myclass> m_Xmls;
};
class Myclass
{
// ...
};
I'd like to make a friend function of a class from a global namespace, which seems to work fine, unless the friend function uses a custom return type like this:
typedef int Type;
Type myFunction();
namespace foo {
class Foo
{
public:
friend Type ::myFunction();
private:
void bar() {}
};
}
Type myFunction()
{
foo::Foo a;
a.bar();
return 0;
}
If int is used instead of Type the code compiles, but with the typedef the compiler does not seem to separate the type from the namespace, and gives an error:
error: expected a class or namespace
friend Type ::myFunction();
^
error: C++ requires a type specifier for all declarations
friend Type ::myFunction();
I'm using clang++ 500.2.79 on OS X.
I could use #define instead of typedef as a workaround in the example, but in my real-world issue the custom type is coming from another header file, which cannot be changed.
Any help would be appreciated.
This works in GCC, but doesn't work in VS13, or as you said, in clang++. However, this fixed the problem in VS13:
friend Type (::myFunction());
I have been experimenting with code derived from the "C++ Seasoning" presentation by Sean Parent, and have boiled my problem down to the following code:
#include <memory>
struct container {
struct concept {
virtual ~concept() {}
virtual void foo_() = 0;
};
template <class T> struct model : concept {
model (T x) : data_(x) {}
void foo_() {
foo(data_); // Line 13
}
T data_;
};
template <class T>
container(T x) : self_(new model<T>(x)) {} // Line 20
std::unique_ptr<concept> self_;
friend void foo(container &c) { c.self_->foo_(); }
};
void foo(int i) // Line 27
{
}
int main()
{
int i = 5;
container c(i); // Line 34
foo(c);
}
The problem I have is that this code that compiles with g++, and yet not with Clang.
Clang gives me the following error messages:
prio.cpp:13:13: error: call to function 'foo' that is neither visible in the
template definition nor found by argument-dependent lookup
foo(data_);
^
prio.cpp:20:32: note: in instantiation of member function
'container::model<int>::foo_' requested here
container(T x) : self_(new model<T>(x)) {}
^
prio.cpp:34:15: note: in instantiation of function template specialization
'container::container<int>' requested here
container c(i);
^
prio.cpp:27:6: note: 'foo' should be declared prior to the call site
void foo(int i)
^
My understanding is that overload resolution during templates occurs at the point of instantiation. In this case, that is line 34 (as marked above.) At this point, the global "foo" function is known. And yet, it appears not to resolve.
Note for posterity: This was with Clang built from trunk on 14/Jan/14
Is this a bug in Clang then, or with g++?
Gcc is wrong in this case, the code should not compile; but this is completely unrelated to the template. Friend declarations are particular in that they provide a declaration for a namespace level entity, but the declaration is not visible for normal lookup until a namespace declaration is also seen by the compiler.
Consider the simplified example:
struct X {
friend void f(int); // [1]
void g() { f(1); } // [2]
};
void h() { f(1); } // [3]
void f(int); // [4]
void i() { f(1); } // [5]
The friend declaration [1] inside the X class provides a declaration for a namespace level function f taking an int, but that declaration is not visible at namespace level until a namespace level declaration is present in [4]. Both [2] and [3] will fail to compile, although [5] will compile since at that point the compiler will have parsed the function declaration.
So how can the declaration in [1] be used by the compiler to resolve a call? In this particular case never. The friend declaration can only be found by argument dependent lookup, but ADL will only look inside X if one of the arguments to the function call is of type X. In this case, the function does not have any argument X, so lookup will never use the friend declaration for anything other than lifting the restrictions of access to the variables of X.
That is:
struct Y {
friend void f(int) {}
};
Without a latter namespace level declaration for f will declare and define a function that cannot be used anywhere in your program (lookup won't ever find it).
The simple workaround for your problem is to provide a declaration for the function at namespace level before the definition of the class:
#include <memory>
void foo(int);
struct container { // ...