VS2013 Intellisense doesn't understand decltype - c++

Is there a patch out there (official or unofficial) to get IntelliSense to stop reporting every use of decltype as a syntax error? It compiles fine, so I know decltype is supported, but it's very distracting seeing red squiggles everywhere and makes it much harder to find actual errors in the code. Every compile gives me a list of hundreds of non-errors - basically at least 3 for every use of decltype in the code base, e.g.:
std::for_each(std::begin(list), std::end(list), [](const decltype(list)::value_type& item)
{
<do stuff with item>
});
will produce the following (non) errors:
IntelliSense: global-scope qualifier (leading '::') is not allowed
IntelliSense: expected a ')'
IntelliSense: identifier "item" is undefined
Upgrading to VS2015 is not an option at this point. (I doubt I could convince the company to shell out to upgrade every computer, and upgrading only some of them would lead to backwards compatibility issues.)
Personally, I'd prefer not to use decltype at all until we get an IDE that fully supports it (there's nowhere I know of that you actually need it), but I don't think I can convince everybody of that either. I just want to make all those fake errors go away so that I can find the real ones without poring over thousands of false-positives.

Given a helper template alias
template <typename T> using id = T;
you can avoid the Intellisense errors, while still keeping the code perfectly valid, by writing id<decltype(list)>::value_type where you would otherwise have written decltype(list)::value_type.
Depending on how often decltype is immediately followed by ::, you may want to create a macro as simple as:
#define DECLTYPE(x) id<decltype(x)>

Related

Why is LLDB's print (or p) command so limited?

When I first heard about it, it sounded like a great feature—a c++ REPL. However, it cannot call STL functions or methods, and has a whole lot of other issues. This question also applies to conditional breakpoints.
Is it still an experimental feature, or have the developers just dropped it?
Example:
(lldb) p iterator->aField
error: call to a function 'std::__1::__wrap_iter<aClass const*>::operator->() const' ('_ZNKSt3__111__wrap_iterIPK8aClassEptEv') that is not present in the target
error: 0 errors parsing expression
error: The expression could not be prepared to run in the target
At present, there's no good way for the debugger to generate methods of template specializations for which the compiler only emitted inlined versions. And the debugger can't call inlined methods.
Here's one limited trick (though it requires C++11) that you can use to force the compiler to generate full copies of the relevant template class so that there are functions the debugger can call. For instance, if I put:
template class std::vector<int>;
in my source code somewhere, the compiler will generate real copies of all the functions in the int specialization of std::vector. This obviously isn't a full solution, and you should only do this in debug builds or it will bloat your code. But when there are a couple of types that you really call methods on, its a useful trick to know.
You mention a "whole lot of other issues". Please file bugs on any expression parser issues you find in lldb, either with the lldb bugzilla: https://llvm.org/bugs, or Apple's bug reporter: http://bugreporter.apple.com. The expression parser is under active development

Can't compile va_arg() call using templated type because of comma in template parameters

This line:
minimum= va_arg(arguments, Vector<T, dimension_count>);
Won't compile because the comma makes the compiler think there's three arguments instead of two. This I figured out several months ago when I first wrote it. My workaround was to simply put the template type inside of a set of parenthesis. This worked in Visual Studio's compiler up until today, when I switched to G++, which refuses to compile because it
"expected type-specifier before '(' token".
So it appears I'm damned if I do, damned if I don't. Help would be very much appreciated.
Use a typedef to turn your Vector type into a simpler name with no commas in it.

Why isn't using #define to hide unique_ptr ugliness working here?

What is wrong with the following "trick" for hiding unique_ptr ugliness?
class Drawable;
typedef unique_ptr<Drawable> pDrawable;
#define newDrawable(...) pDrawable(new Drawable (##__VA_ARGS__))
The first two are fine. But the third one is causing an error in VS2012:
23 IntelliSense: "std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx>::
_Myt &) [with _Ty=Drawable, _Dx=std::default_delete<Drawable>]" (declared at line 1447 of
"C:\vs2012\VC\include\memory") is inaccessible file.h 36 26
I don't see why this wouldn't work, unless I am misunderstanding how C++ define macros work. I thought that it would simply replace this code:
newDrawable(a, b, c)
with
unique_ptr<Drawable>(new Drawable(a, b, c));
I understand that unique_ptr cannot be copied, but I am not copying it, here. Am I?
edit:
I have received some requests for "use" of the macro in question:
If I were to use it, it would be used as follows:
pDrawable myDraw = newDrawable();
which I would want to translate to:
unique_ptr<Drawable> myDraw = unique_ptr<Drawable>(new Drawable());
However, I cannot even compile the macro without visual studio giving the below error. It's as if something in the #define is impermissible, per se. The error is returned on the line where I make the define, not where I call the define.
See here for why make_unique doesn't work: make_unique does not compile
edit2
I have answered the question below. The code above does compile, and work.
Well, #define is, IMHO, a huge problem because it doesn't obey scoping rules and they do simple textual substitution that can sometimes have surprising results. I consider preprocessor macros to be the last resort when I need to get something done.
It would be much better to define a template like make_shared that returned a unique_ptr<T>. This is allowable because you could then move it into place.
auto a_drawable = make_unique<Drawable>(a, b, c);
template <typename T, typename... Args>
::std::unique_ptr<T> make_unique(Args&&... args)
{
return ::std::unique_ptr<T>{new T(::std::forward<Args>(args)...)};
}
That's much cleaner than the macro, and it works for any non-array type. Which is a problem. It can be made to work for array types as well, but that code is a bit more complex, and rather than repeat it, I'll just point at the answer a helpful commenter referred me to:
make_unique and perfect forwarding
As for why you're getting the error you do when you use your macro, I'm not sure. It looks like you're using your macro in some context where the result gets turned into a const ::std::unique_ptr<Drawable> &, and then tries to move construct it into a different pDrawable. This won't work. Why that's happening, I don't know. It depends crucially on the context in which you're using the macro, and you haven't provided that.
And that just highlights my first point. One reason macros are really ugly because they are simple textual substitution and their meaning can change depending on context.
Answer:
Make sure you actually use the macro, and everything will be ok.
Apparently, in an attempt to validate #define macros, VC++ checks your actual use of the macro. If there is no actual use of the macro compiled, VC++ tries to "understand" it, and can throw compiler errors.
Magically, if I add:
pDrawable myDraw = newDrawable();
After my code above, the error disappears.
Sorry for wasting everyone's time. At least this inspired me to read the following article:
http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx

boost::bind doesn't work in VC++ 2010 when binding a function that throws exceptions

I have some code which compiles fine under Linux, but I am trying to port it to Windows. I have used the Boost 1.50 precompiled binaries from Boost Pro, but when I compile my code I get this cryptic error:
error C2664: 'boost::_bi::bind_t<R,F,L>::bind_t(const boost::_bi::bind_t<R,F,L> &)' :
cannot convert parameter 1 from 'boost::_bi::bind_t<R,F,L>'
to 'const boost::_bi::bind_t<R,F,L> &'
C:\Program Files (x86)\boost\boost_1_50\boost\bind\bind_cc.hpp [line] 50
The error is most unhelpful because it shows up deep in the Boost header files, with no indication of where in my code the problem is. Nevertheless by commenting out various blocks of code I have narrowed it down to this as the cause:
void test(int a)
throw (int) // removing this line makes it compile
{
return;
}
...
boost::function<void(int)> fn = boost::bind<void>(test, _1);
It works if I remove the throw specifier in the function definition. It doesn't matter what I throw, whether it's a class or just an int. Am I doing something wrong, or can't you bind to functions that throw exceptions in Visual C++? The Boost Bind docs don't seem to suggest any issues with this, and GCC doesn't have a problem with it either way.
[Side note: The code above is not my actual code, but when compiled it exhibits the same problem. Please avoid comments about throwing ints being bad and the like, as this is only supposed to be a trivial example in case anyone wishes to reproduce the problem.]
I don't know why your code fails on VC++. However, in general exception specifications are best avoided because they can introduce very subtle effects. See this excellent column A Pragmatic Look at Exception Specifications by Herb Sutter:
So here’s what seems to be the best advice we as a community have
learned as of today:
Moral #1: Never write an exception specification.
Moral #2: Except possibly an empty one, but if I were you I’d avoid
even that.

How to debug template arguments at compile-time?

I have a piece of code that pretty much reduces down to:
template<class T> struct MyStruct; // No definition by default
template<class T> struct MyStruct<T *> { ... }; // Specialization for pointers
Now somewhere in my code, I'm getting an instantiation of MyStruct<T> that happens to be undefined (no C++0x/011, no Boost... nothing fancy, just plain C++03):
error C2027: use of undefined type 'MyStruct<T>'
The trouble is, I have no idea where this is being caused, because the code that's doing the instantiation is itself a template, and called from numerous places, with different arguments.
Is there a way to somehow figure out what T is at compile-time, so I can understand the error messages better?
(Sorry, I forgot to mention: Visual Studio 2008.)
I believe you're using MSVC++, if so, then see the output window, it might have more info printed, especially the line number along with the filename. Once you know the file and line number, you can start from there.
Output window usually prints everything, like how and with what template argument(s), a template is instantiated. Everything step by step. Those messages are very useful when debugging.
As you found yourself, enabling /WL prints more detail messages in the output window.
I know you said no C++11, but you may want to consider, since C++03 code is backwards compatible in all C++11 compliant compilers, to use the static_assert feature of C++11 to debug your code ... if you must do the final compile with a C++03 compiler, then you can always create a #define and use the #ifdef and #endif pre-processor macros to make sure that the static_assert feature does not cause problems in earlier compilers that do not support C++11 features.
See the MSDN docs here for more info.