Does Visual C++ 2008 support function try block inside methods?
I tried this code:
class Foo
{
public:
void f()
try {}
catch ( ... ) {}
};
but the compiler prints this error:
error c2590: 'f' : only a constructor can have a base/member initializer list
The same syntax (valid, according to the standard) works inside a free function.
The code compiles on newer versions of Visual Studio and on gcc.
EDIT: no, in my code there is not a typo. C++ standard says it's a valid syntax. It's called "function try block".
EDIT 2: if I move the method definition outside the class definition, visual c++ 2008 compiles correctly.
Thanks.
This features is only valid for constructors to catch exceptions in inline initializations of member variables, example:
struct a {
a(const complex_object& value)
: m_var(value)
{}
private:
complex_object m_var;
};
If there is an exception throw in copy constructor of complex_object there is no way of handled (no without changing the initialization of m_var).
http://msdn.microsoft.com/en-us/library/e9etx778%28v=vs.90%29.aspx
In this case the function-try block are used to handled such exception maintaining the same initialization.
In your case method f is not a constructor of class Foo.
Daniele is right Function-Try Block could be used in methods, but normally this don't improve much, in this case is better a try-catch block inside method body (permitting returning values from catch block if necessary).
VS2008, was not a version focused in standardization of C++, VS2010 improve this problem but i think not enough, later version VS2012 and specially VS2013 are really getting close to conformant enough (specially in day to day usage), they have some remaining old hard problems, two phases lookups and preprocessor, that in corner case can blow your mind trying to solved, specially treating with portable code (compiled addicionally with GCC, Intel, etc...), but the actual status is really improved.
Related
I'm writing an iterator for a new container in c++. When I call begin() and end() functions (both very short), I expected the compiler to make it inline. But it didn't. I think maybe it's because the iterator is returned as a temporary object, and it needs to be copied. I think maybe I can use the RValue reference in c++11, but I'm not familiar with it. So is there a way to make it inline?
The code is something like this (not exactly the same, but I think if this version works, my code will also work)。
I'm using VC++ 2013 CTP, and I have changed compile options but it doesn't work either.
class Pointer
{
public:
Pointer(int* p) : p(p)
{
(*p)++;
}
Pointer(const Pointer& pointer) : p(pointer.p)
{
(*p)++;
}
Pointer& operator =(const Pointer& pointer)
{
(*p)--;
p = pointer.p;
(*p)++;
}
int* p;
~Pointer()
{
(*p)--;
}
static Pointer create(int& p)
{
return Pointer(&p);
}
static Pointer create2(int& p)
{
return create(p);
}
};
int main()
{
int p = 0;
Pointer pointer = Pointer::create2(p);
}
The function create and create2 here are not inline even if, you can see, it's really simple.
I know maybe this doesn't make a difference in the speed of my program, but I just want to have it better.
There are several cases where microsoft's compiler cannot inline functions:
http://msdn.microsoft.com/en-us/library/a98sb923.aspx
In some cases, the compiler will not inline a particular function for mechanical reasons. For example, the compiler will not inline:
A function if it would result in mixing both SEH and C++ EH.
Some functions with copy constructed objects passed by value when -GX/EHs/EHa is on.
Functions returning an unwindable object by value when -GX/EHs/EHa is on.
Functions with inline assembly when compiling without -Og/Ox/O1/O2.
Functions with a variable argument list.
A function with a try (C++ exception handling) statement.
Because the functions return Pointer by value and it has a destructor, the functions cannot be inlined.
There's nothing that can really be done about it other than changing the Pointer class. Rvalue refs don't help here. I would just leave the code as it is and if you need better performance in final product, try another compiler.
RVO may happen here but it doesn't make difference because the cost of copying is so small.
In the C languages there is simply no way to force inlining. inline is just a hint to the compiler to perform inlining, but it is not required to do so.
The only way to "force inline" would be to use preprocessor macros, but that's easy to get wrong. Wrong in that the macro doesn't do what you expect, and wrong in that the macro actually produces slower code. Also, preprocessor macros are no substitute for member functions.
So, if the compiler doesn't want to inline, there's not much you can do about it, and nothing you should do about it.
The answer by Timo is correct for any combination of the /EH?? flag (and /EH?? must be specified to allow any useful exception handling), specifically, MSVC Studio-2015 as well as Studio-2017 15.1 and 15.2 versions will not ever inline a function call if a D'tor is present.
However, I recently found a UserVoice Issue -- Support inlining for functions returning unwindable objects -- for this: (Dec', 2016)
Within deeply-templated codes, it seems quite common to call a
function which simply forwards the arguments into another function,
which again just forwards the arguments into another function, which
again just do forwarding, and so on. As I know, current version of
Visual C++ is not able to inline such a function if it returns an
object with non-trivial destructor, whenever exceptions are enabled.
This often makes a performance hit particularly when the level of
forwarding is unavoidably deep and there are many arguments with
not-so-small sizes. I very much hoped if the upcoming Visual C++ 2017
has solved this problem, but it seems not.
And a comment that states it will be fixed in VS2017 v15 .3 and links to a connect issue where a comment states:
The inlining limitation was because of the presence of exception handling. We have recently improved our inliner and it can now inline std::make_unique in the case you provided. Please download the latest VS 2017 version to try it out. Note that in VS 2017 RTM, this new inlining is off by default, but you can turn it on by adding the flags /d1ReturnUdtEHInline /d2ReturnUdtEHInline to cl.exe. It will be on by default in a future release.
Note that /d1 and /d2 switches are undocumented switches for the front/backend of the compiler.
and
You should expect it to be on by default in the VS 2017 15.3 release.
So, maybe there's hope this will be actually fixed in VS2017 U3.
Two short Godbolt examples to experiment with:
https://godbolt.org/g/1y9UpE
https://godbolt.org/g/3mAzGe
I am using googlemock to mock out an std::fstream object in my unit tests, like this:
TEST_F(SomeTest, SomethingIsDoneCorrectly)
{
class MockFstream : public std::fstream {};
MockFstream lMockFstream;
// Expectations and assertions here
}
When I compile I get the following warnings:
Warning 1 warning C4250: 'SomeTest_SomethingIsDoneCorrectly_Test::TestBody::MockFstream' : inherits 'std::basic_istream<_Elem,_Traits>::std::basic_istream<_Elem,_Traits>::_Add_vtordisp1' via dominance
Warning 2 warning C4250: 'SomeTest_SomethingIsDoneCorrectly_Test::TestBody::MockFstream' : inherits 'std::basic_ostream<_Elem,_Traits>::std::basic_ostream<_Elem,_Traits>::_Add_vtordisp2' via dominance
I'd prefer clean build output, so I want to suppress these specific warnings, but I'm writing cross-platform code, so I'd also prefer to avoid compiler-specific #pragmas.
Is there something I can do in the googlemock object that will hide these warnings?
It turns out that these warnings are a side-effect from some quirks in the Microsoft C++ STL. I've quoted an explanation from the relevant Microsoft Connect issue below.
My solution was simply to implement empty versions of the inherited functions in my mock:
TEST_F(SomeTest, SomethingIsDoneCorrectly)
{
class MockFstream : public std::fstream
{
void _Add_vtordisp1() { } // Required to avoid VC++ warning C4250
void _Add_vtordisp2() { } // Required to avoid VC++ warning C4250
};
MockFstream lMockFstream;
// Expectations and assertions here
}
An explanation from Microsoft about why the warning occurs:
The story here is somewhat complicated. VC has an obscure compiler option, /vd2 (documented at http://msdn.microsoft.com/en-us/library/7sf3txa8.aspx), that fixes an obscure bug involving virtual base classes. By default, VC does something that's slightly nonconformant to the C++ Standard. /vd2 changes VC's behavior to be conformant, but this inherently affects class layout. (This layout difference is why the default hasn't been changed to be conformant - that would break users attempting to mix code compiled with different major versions of VC. Our C++ Standard Library implementation forbids such mixing, but the compiler itself is somewhat more permissive.) So if users want /vd2, they have to compile everything that way.
The twist is that the layout bug (which /vd2 fixes) affects iostreams, which uses virtual base classes, and our iostreams implementation has a separately compiled component (in msvcp100.dll/libcpmt.lib/etc.). When MS builds the STL's DLL/LIB, they're compiled the default way, without /vd2. As a result, people using /vd2 couldn't use iostreams, or they'd get bizarre crashes. Yuck.
So, we added the do-nothing virtual functions _Add_vtordisp1() and _Add_vtordisp2(). Their presence makes VC perform layout completely conformantly, regardless of /vd2 being used or not, and therefore makes iostreams usable both ways.
_Add_vtordisp1() and _Add_vtordisp2() trigger warning C4250, talking about dominance. This warning is actually completely useless - it's saying that the compiler will do exactly what the Standard requires it to do. Therefore, we suppress it in the STL's headers (which must be /W4 /analyze clean). If you're deriving from fstream, you'll need to suppress this warning in your own code.
I'm a student, and I'm trying to write and run some test code for an assignment to check it before I turn it in. What I'm trying to do now is test that my code prevents value semantics properly. In my assignment, I have declared for each of my classes its own private copy constructor and assignment operator that have no definition, and so do nothing. When they are called in my test program, I am getting compile errors like I expected. Something like this:
error: 'myClass::myClass(const &myClass)' is private'
error: 'myClass& myClass::operator=(const myClass&)' is private
Is there a way to use try/catch so that my test code will compile and run, but show me that these errors did occur?
I've tried:
myClass obj1(...);
myClass obj2(...);
try{
obj1 = obj2;
throw 1;
}
catch(int e){
assert(e==1);
}
but the compiler is still giving me the above errors. Are these not 'exceptions'? Will they not trigger a throw?
If I'm understanding try/catch correctly, it handles runtime errors, not the kind errors I was getting above, correct?
After doing some more research, it seems that there is no (easy) way of testing for certain compile errors natively within C++ (this maybe true for most languages, now that I think about it). I read a post that suggests writing some test code in a scripting language that attempts to compile snippets of C++ code and checks for any errors, and another post that recommends using Boost.Build.
What is the easiest/best way of doing what I'm trying to do?
I looked at the documentation for Boost.Build and it's a bit over my head. If I used it, how would I test that a file, say 'test.cpp' compiles, and maybe handle specific compile errors that occur with 'test.cpp'?
Thanks for your help!
P.S. This is one of my first posts, hopefully I've done "enough" research, and done everything else properly. Sorry if I didn't.
These are compiler errors, not exceptions. Exceptions are a mechanism for programmers to throw run-time errors and catch/handle them. The compiler fails to even build an executable for you to run because it recognizes that the code is malformed and is invalid C++ code.
If you want to make this a run-time error, make the method public/use friends/whatever you need to do to provide access to something and throw an exception in the method's definition, the catch and handle the exception in the calling code.
I don't see a purpose in doing this however. Always prefer a compile-time error to a run-time error. Always.
The C++ standard defines what is valid or invalid code, with some things left as undefined and other things left up to whoever implements the compiler. Any standard compliant C++ compiler will give an error because something does not meet the standard/definition and is thus invalid. The errors are generally to say that something is ambiguous or straight up nonsensical and you need to revise what you've written.
Run-time errors are either crashes or behavior that is unintended and unwanted from the perspective of the user. Compiler errors are the compiler saying "I don't understand what you're saying. This doesn't make sense.". Compiler warnings are the compiler saying "I'll let you do this, but I probably shouldn't. Are you really sure this is what you meant?".
try-catch happens at runtime, whereas the compiler statically tries to link functions you are calling at compile time, so compilation will always fail.
Alternatively, If you are willing to use C++ exceptions, then you could just implement the copy and assignment methods, make them public, and just throw an exception in the body of those functions. Note that in basically every situation, you should prefer static/compile-time checks over runtime checks if you have a choice.
What you really want to test is not the compiler failing, but you want to test certain assumptions about your class.
In your test file, put #include <type_traits>
and then add
assert((std::is_assignable <myClass, myClass> ::value) == FALSE);
assert((std::is_copy_assignable<myClass> ::value) == FALSE);
assert((std::is_copy_constructible<myClass> ::value) == FALSE);
The various traits you can check for are documented here:
http://en.cppreference.com/w/cpp/types
Notice, you'll have to compile for C++11 to use most of these functions.
(as described first in Assert that code does NOT compile)
After doing some more research, it seems that there is no (easy) way of testing for certain compile errors natively within C++
I think this might not be the case anymore if you can use C++2a.
As I am currently writing tests for templated code, I also tried to test for compile time errors.
In particular, I want to test for a negative feature, hence provide a guarantee that certain construct will fail to compile. That is possible using c++20 requires expressions as follows:
Simple example
Below, I check that the nonexistent function invalid_function cannot be called on a Struct of type S:
struct S {}; //< Example struct on which I perform the test
template <typename T> constexpr bool does_invalid_function_compile = requires(T a) {
a.invalid_function();
};
static_assert(!does_invalid_function_compile<S>, "Error, invalid function does compile.");
Note that you could replace the static_assert by the apporpriate function of your testing framework, which records a test error at runtime and hence avoids this compile test to stop other tests from executing.
Example form question
This example can of course be adapted to work with the scenario depicted in the question, which might look approximately like this:
/// Test struct with deleted assignment operator
struct myClass {
auto operator=(myClass const &) = delete;
};
/// Requires expression which is used in order to check if assigment is possible
template <myClass cl1, myClass cl2> constexpr bool does_assignment_compile = requires() {
cl1 = cl2;
};
int main() {
myClass cl1;
myClass cl2;
// Note that static assert can only be used if this can be known at compile time. Otherwise use
// the boolean otherwise.
static_assert(!does_assignment_compile<cl1, cl2>);
}
The code is available on Compiler Explorer.
Use cases
I use this for template metaprogramming in order to make sure that the code complies with certain theoretical constraints.
This kind of compile errors can't be supressed. They are errors from the C++ standarts' point of view.
Surely you can supress some of them in your own (or patched) compiler.
Was std::string.npos ever valid? (As opposed to the correct std::string::npos.)
I am seeing it a lot in an old project I'm working on, and it does not compile with VS2010.
Is it something from the pre-standard days?
The C with classes syntax for naming a class member was, in fact, a dot:
class X {
public:
void f();
};
void X.f() // a dot! see D&E 2.3
{
}
However, the :: syntax had not yet been invented. The std namespace didn't exist yet either. Thus the std::string.npos wasn't ever valid as either C with classes or standard C++.
I suspect std::string.npos is purely Microsoft's extension (or a bug?). It might be inspired by the old syntax, and might be not.
No, std::string.npos was never valid, and no, it's not something from the pre-standard days.
I see other answers mentioning that MSVC has allowed that notation.
However, MSVC is not a very compliant compiler. For example, it lets you freely bind a temporary to a reference to non-const. For another example, for Windows GUI subsystem applications you have to use not well-documented switches to make it accept a standard main. Much has improved since Microsoft hired Herb Sutter (and other guy that I don't remember the name of right now) to fix up their monstrous compiler. And in relative terms it has been really great, but in absolute terms, well that compiler is still a bit lacking.
Access to any static member via class name and dot was unfortunately allowed by prior versions of MSVC.
#include <iostream>
struct A
{
static int a;
};
int A::a;
int main()
{
std::cout << A.a;
}
This code is happily accepted by MSVC9.0 with a warning
Warning 1 warning C4832: token '.' is
illegal after UDT 'A'
The C++ standard obviously disallows access to a static member via className.memberName (although it is perfectly legal to access a static member via an object object.staticMemberName).
My common sense tells me that if MSVC is aware that this is not standard and gives a warning, then we can turn that extension off. We go to Project Propertied -> C/C++ -> Language and set Disable Language Extensions to Yes. Do you think anything changes? Of course not, the compiler still accepts the illegal code with the same warning. I sometimes wonder what Disable Language Extensions actually does...
Hi i have to port some stuff written on c++ from unix bases os to windows visual studio 2008.
The following code implements array data type with void ** - pointer to the data.
struct array
{
int id;
void **array; // store the actual data of the array
// more members
}
When i compile with g++ on Unix it's ok but when i try with MSVS 2008 I get the error - error C2461: 'array' : constructor syntax missing formal parameters. When i change the member from 'array' to something else it works, so it seems that the compiler thinks that the member name 'array' is actually the constructor of the struct array. It's obviously not a good practice to name the member like the struct but it's already written that way. Can i tell the MSVS compiler to ignore this problem or i should rename all members that are the same as the struct name.
You are dealing with a bug in GCC compiler. C++ language explicitly prohibits having data members whose name is the same as the name of the class (see 9.2/13). MS compiler is right to complain about it. Moreover, any C++ compiler is required to issue a diagnostic message in this case. Since GCC is silent even in '-ansi -pedantic -Wall' mode, it is a clear bug in GCC.
Revison: What I said above is only correct within the "classic" C++98 specification of C++ language. In the most recent specification this requirement only applies to static data members of the class. Non-static data members can now share the name with the class. I don't know whether this change is already in the official version of the revised standard though.
That means that both compilers are correct in their own way. MS compiler sticks to the "classic" C++98 specification of the language, while GCC seems to implement a more recent one.
I'd say that if you're doing something that you yourself describe as "not a good practice", then you should change it.
I would rename your attribute to not have the same name as the class. This will make your code more portable. If you have to move to yet another compiler in the future, you won't run in to this problem again then.