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.
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 have a nice question about the loop-expression of a for-loop in C#.
I always like to learn and extend my knowledge so I often use my reflector to look and learn from other. Lately I was looking around in an assembly which I assume is a C# assembly.
I came across this:
public virtual void DoRows(Parse rows)
{
for (; rows != null; {
Parse more;
rows = more;
}
)
{
more = rows.More;
this.DoRow(rows);
}
}
I never knew I could use a code-block in my loop-expression. So I fired up MSDN and went looking in the language reference of C# but found nothing.
The C++ reference shows some interesting things tho (http://msdn.microsoft.com/en-us/library/b80153d8.aspx), but I am not a C++ developper and I have a strong feeling the assmbly was not written in C++.
dotPeek says the assembly is a v4.0.30319 / msil assembly.
Now here are the questions:
- Is this a C++ or a C# code-construct?!
- Can we do things like this in C#?
I am not able to reproduce code that looks like that and compiles in VS2010.
#edit: changed the word assembly in code-construct.
#edit II: Thanks for all your answers. I think this is either a bug in the dotPeek reflector or we found some for-loop-expression easter eggs. This is what Red Gate says about the same method:
public virtual void DoRows(Parse rows)
{
while (rows != null)
{
Parse more = rows.More;
this.DoRow(rows);
rows = more;
}
}
There is no such thing as a C++ or C# assembly. Once the code is compiled, it is ILCode. The reflector takes this ILCode and decompiles it to the language you selected.
This can result in code that is valid in ILCode, but not valid in the target language.
Compilation to IL is a many-to-one operation and decompilers have rules regarding which of the many choices they choose when decompiling. Often, different languages produce IL that is not possible to reproduce directly in another language.
In this instance either the decompiler has chosen poorly and the produced C# is invalid (a bug in the decompiler), or it cannot decompile the code into equivalent C#.
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.
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.