I have a vector class that I want to be able to input/output from a QTextStream object. The forward declaration of my vector class is:
namespace util {
template <size_t dim, typename T>
class Vector;
}
I define the operator<< as:
namespace util {
template <size_t dim, typename T>
QTextStream& operator<<(QTextStream& out, const util::Vector<dim,T>& vec)
{
...
}
template <size_t dim, typename T>
QTextStream& operator>>(QTextStream& in,util::Vector<dim,T>& vec)
{
..
}
}
However, if I ty to use these operators, Visual C++ returns this error:
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'QTextStream' (or there is no acceptable conversion)
A few things I tried:
Originaly, the methods were defined as friends of the template, and it is working fine this way with g++.
The methods have been moved outside the namespace util
I changed the definition of the templates to fit what I found on various Visual C++ websites.
The original friend declaration is:
friend QTextStream& operator>>(QTextStream& ss, Vector& in) { ... }
The "Visual C++ adapted" version is:
friend QTextStream& operator>> <dim,T>(QTextStream& ss, Vector<dim,T>& in);
with the function pre-declared before the class and implemented after. I checked the file is correctly included using:
#pragma message ("Including vector header")
And everything seems fine. Doesn anyone has any idea what might be wrong?
Note: the definition of the operator doesn't even appears in the list of operator<< found.
I encountered the same problem and I think I figured out what was going on. For some reason, MSVC sometimes mistakes std::endl, for the endl defined in QTextStream (of course if you are "using namespace std" anywhere, this behavior is appropriate).
Also, I think MSVC sometimes gets confused with std::strings (maybe if they are const or addresses or something like that) with QTextStream.
MSVC tends to be very particular about the const/& variants of overloads, especially in cases where there may be some ambiguity. I have seen this before with non-QT code with some overloaded functions.
Of course, the error messages are just confusing so, it might be that my analysis is wrong here.
It is hard to say without seeing the actual instantiation site, but so far what I noticed is that the error says that there is no suitable operator for QTextStream, and your implementations use QTextStream&. This might be because you are trying to use the operator on an R-Value, these can be converted to const &, but not only &.
You forgot to make the overload that took a const Vector actually const.
Related
I'm writing a grammar for C++ target, however I'd like to keep it working with Java as well since ANTLR comes with great tools that work for grammars with Java target. The book ("The Definitive ANTLR 4 Reference") says that the way of achieving target independence is to use listeners and/or visitors. There is one problem though. Any predicate, local variable, custom constructor, custom token class etc. that I might need introduces target language dependence that cannot be removed, at least according to the information I took from the book. Since the book might be outdated here are the questions:
Is there a way of declaring primitive variables in language independent way, something like:
item[$bool hasAttr]
:
type ( { $hasAttr }? attr | ) ID
;
where $bool would be translated to bool in C++, but to boolean in Java (workaround would be to use int in that case but most likely not in all potential targets)
Is there a way of declaring certain code fragments to be for specific target only, something like:
parser grammar testParser;
options
{
tokenVocab=testLexer;
}
#header
<lang=Cpp>{
#include "utils/helper.h"
}
<lang=Java>{
import test.utils.THelper;
}
#members
<lang=Cpp>{
public:
testParser(antlr4::TokenStream *input, utils::THelper *helper);
private:
utils::THelper *Helper;
public:
}
<lang=Java>{
public testParser(TokenStream input, THelper helper) {
this(input);
Helper = helper;
}
private THelper Helper;
}
start
:
(
<lang=Cpp>{ Helper->OnUnitStart(this); }
<lang=Java>{ Helper.OnUnitStart(this); }
unit
<lang=Cpp>{ _localctx = Helper->OnUnitEnd(this); }
<lang=Java>{ _localctx = Helper.OnUnitEnd(this); }
)*
EOF
;
...
For the time being I'm keeping two separate grammars changing the Java one and merging the changes to C++ one once I'm happy with the results, but if possible
I'd rather keep it in one file.
This target dependency is a real nuisance and I'm thinking for a while already how to get rid of that in a good way. Haven't still found something fully usable.
What you can do is to stay with syntax that both Java and C++ can understand (e.g. write a predicate like a function call: a: { isValid() }? b c; and implement such functions in a base class from which you derive your parser (ANTLR allows to specify such a base class via the grammar option superClass).
The C++ target also got a number of additional named actions which you can use to specify C++ specific stuff only.
I have a C++ project that is configured to use CLR. The project contains a subclass of CTreeCtrl, i.e. a class provided by Microsoft that I have no control over. Since the public interface of CTreeCtrl heavily uses the type HTREEITEM, it is unavoidable that the subclass also makes use of the type - but since the type is "opaque", the subclass only passes around HTREEITEM references without actually doing anything with the referenced objects.
By "opaque", I mean that HTREEITEM is only visible as a forward-declared type. Here's the declaration that I see in CommCtrl.h:
struct _TREEITEM;
typedef struct _TREEITEM *HTREEITEM;
Unfortunately, in a release build this usage of HTREEITEM generates the following linker warning:
foo.obj : warning LNK4248: unresolved typeref token (01000017) for '_TREEITEM'; image may not run
Here is the MSDN link for the warning. I have searched the net for a solution to get rid of the warning, but have found nothing - only confirmation that over the years other people have encountered this warning in relation to HTREEITEM as well.
Now I have been thinking of a workaround myself. Given that
My class only gets HTREEITEM references from CtreeCtrl and passes them back to CtreeCtrl, without any kind of interpretation or function calls
HTREEITEM is merely a pointer to _TREEITEM
It follows that all that my class ever does is pass around pointers to _TREEITEM. My idea for a workaround therefore is this: Why not define _TREEITEM as an empty struct in my project, like this:
struct _TREEITEM
{
};
Obviously this makes the linker happy since it now sees the complete type. The fact that the struct definition is incorrect is not relevant since my class is only passing around pointers to _TREEITEM, i.e. all that the compiler needs to know is the size of a HTREEITEM.
I have tried this workaround and it seems to work, not only at compile time but at runtime as well. So what do you think of this workaround? Did I overlook something? I certainly won't be offended if you call it an ugly hack :-)
FWIW: I am currently on Visual Studio 2010.
I just filed this bug on Microsoft Connect regarding the inability to compile the following toy snippet of code:
template <typename... P> struct S {
template <void(*F)(P...)> static void T() { }
};
void A(int, float) { }
int main() { S<int, float>::T<&A>(); }
The error is:
test.cpp(2): error C3520: 'P' : parameter pack must be expanded in this context
Essentially, I cannot unpack a variadic type inside of a function signature when used as a template parameter. This code is (I think) legal; at least, GCC 4.7, Clang 3.0, and ICC 13 all support it.
I've seen this SO question but no workarounds are requested or given, which is what I'm looking for.
While not super critical (obviously I've been getting by without variadic templates for many years now) this pattern is of particular importance to some of the work I'd like to do and some articles I'd like to do on C++11 reflection techniques for serialization, script binding, etc. which is something I'd like to be useful to Visual Studio users (as it is by far the dominant compiler toolset in my industry). I'd like to hope that Microsoft's engineers will be able to fix this by 2013 RTM, but I'm not holding my breath.
A toy (from memory this time) sample of how this is being used is something like (minus the macros that make it slightly easier to use):
Reflect<MyType>("MyType")
.bind("GetMatrix", mat44, &MyType::GetMatrix>()
.bind("Display", void, &MyType::Display>();
Of course this can all be done without variadic templates. It just takes large masses of code and accepting limitations to the maximum arity of bound member functions, of course. And yes, passing the functions as a template parameter is of import, due to the nature of how member function pointers work in Visual Studio (variable size) and a desire to achieve efficiency on par with Impossibly Fast C++ Delegates (in my niche of the C++ community, this level of optimization can sometimes actually matter) which negates the option of using std::function or similar designs.
Is there a work-around for this VS bug? Or any other way to use variadic templates to use a (compile-time) function pointer parameter in VC++12?
Not sure why but simplifying with a typedef seems to work:
template <typename... P>
struct S
{
typedef void (*MyFunc)(P...);
template <MyFunc myFunc>
static void foo() {}
};
void foo2(int, float) {}
int main()
{
S<int, float>::foo<&foo2>();
}
At least on the Visual Studio 2013 Ultimate Preview.
[EDIT: further digging revealed a different root issue. I'm rephrasing the question, but leaving the old version below, for consistency with the answer by #Leo]
It seems VC++ (both under VS2005 & VS2010) allows me to dllexport classes with missing implementations! The following code builds fine:
// missingimp.h :
class __declspec(dllexport) MissingImp
{
void DoStuff(); // no implementation anywhere
void DoMoreStuff(); // neither for this
}
// missingimp.cpp
#include "missingimp.h"
The code both compiles and links fine (in dll configuration) - and of course statically linking with the resulting dll fails.
Is this be a bug? is this behavior somehow by design??
[Old question:]
I'm trying to dllexport a class, that has a data member templated on a forward-declared type:
// Class2Export.h:
class ForwardDeclared ;
template<class T> class TemplatedClass
{
T *m_ptr;
public:
TemplatedClass() { m_ptr->DoSomething(); }
};
class __declspec(dllexport) ExportedClass
{
TemplatedClass<ForwardDeclared> TemplateForward;
};
// Class2Export.cpp:
#include "Class2Export.h"
(This is not a contrived example - in the real code TemplatedClass is a smart pointer, but that seems irrelevant to the issue at hand.)
This code fails to compile, with -
error C2027: use of undefined type
'ForwardDeclared'
That still makes some kind of sense, based on a reply from MS:
If TemplatedClass has a constructor
then a constructor will be
automatically generated for
ExportedClass. Since ExportedClass is
exported the compiler tries to export
the constructor but fails to generate
code for it because ForwardDeclared is
unknown.
But I suspect that is not the ultimate answer, as when I declare (without even implementing!) a ctor for ExportedClass:
...
class __declspec(dllexport) ExportedClass
{
ExportedClass();
TemplatedClass<ForwardDeclared> TemplateForward;
};
...
both compile and link succeed (with a due warning*). The issue over at MS-connect seems abandoned - perhaps anyone can shed some light over this strange behaviour?
Thanks!
*EDIT: the generated warning is C4251 :
class 'TemplatedClass ' needs to have dll-interface to be used by clients of class 'ExportedClass'
Unless I've got the wrong end of the stick, the issue is about when the ExportedClass constructor code is generated.
If the ExportedClass constructor code is generated before ForwardDeclared is declared (not forward-declared but properly declared) then you'll get an error, since the ExportedClass constructor implicitly calls the TemplatedClass constructor, and that calls a method on ForwardDeclared which is undefined.
Your final example, the one which compiles and links with a warning, works because the ExportedClass constructor is never defined. (Presumably the warning is that ExportedClass::ExportedClass does not exist. Since nothing actually tries to use it it's just a warning and not an error.) You've avoided the issue there. As it is, that code is not useful as nothing can create ExportedClass (it has no constructor) but if you define the constructor somewhere then everything should work fine, provided ForwardDeclared is declared/defined before then.
If you change your final example to this you should get the errors back again: (All that's added are two braces to give the ExportedClass constructor an empty body)
class __declspec(dllexport) ExportedClass
{
ExportedClass() { } // Error here
TemplatedClass<ForwardDeclared> TemplateForward;
};
And that code is what you are implicitly doing if you don't have a constructor for ExportedClass at all. In these cases the constructor's code is being generated there and then in the header file. On the other hand, when the constructor is declared without a body in the header you are leaving the code to be defined and generated somewhere else.
Eventually I found an answer in MS forums.
I'm linking to it here, in case it's useful to anyone some day.
I was trying to use the OMPTL in Visual Studio. As far as I understand it, I only need to set the /openmp option, in order for the OMPTL to use the multi-threaded implementation of some stl functions.
When I don't use /openmp everything is fine and OMPTL maps the functions to their normal stl counter parts, without multi-threading. With /openmp however, I get a compiler error:
Error 1 error C2572: 'omptl::transform_accumulate' : redefinition of default parameter : parameter 6 ..\include\omptl\omptl_numeric_extentions_par.h 132
The line in question says
template <class Iterator, class T, class UnaryFunction, class BinaryFunction>
T transform_accumulate(Iterator first, Iterator last, const T init,
UnaryFunction unary_op, BinaryFunction binary_op,
const unsigned P = omp_get_max_threads())
{
return ::omptl::_TransformAccumulate
<typename ::std::iterator_traits<Iterator>::iterator_category>
::transform_accumulate(first, last, init,
unary_op, binary_op, P);
}
Is there a way to fix this or is the OMPTL simply not usable with Microsoft's compiler?
The compiler does not seem to accept default parameters in this template declaration. Removing = omp_get_max_threads() from both declarations solved the problem for me.