error C2027: the gcc vs msvc case - c++

This simple snippet of code
class S;
class G
{
void onRead(S & s)
{
(void)s;
}
};
perfectly works on GCC. Using that (void)s is a very useful way to avoid the warning "unused variable 's'". But MSVC sees this as an error, stopping the compilation.
It gives the infamous error C2027: use of undefined type 's'. But here 's' its not used at all.
How can I solve this kind of trouble?
I don't want to use the form of void onRead(S &) because you can't see it in this little snippet example, but in my code that 's' name is really meaningful, and useful to understand the parameters.

There are a couple of alternate ways of avoiding the error.
The most straight-forward is to convert the variable name to a comment:
void onRead(S & /* s */)
Another is to use a macro to remove the variable:
#define UNUSED(x)
void onRead(S & UNUSED(s))
I'm sure you've already thought of just moving the code to a point where S is fully defined and there's some reason you can't do that.

You can't use "s" because the class "S" hasn't been fully defined. You can:
1) Disable the warning with #pragma warning(disable:4100)
2) Move the body of the onRead function to a place where "S" has been fully defined
3) Move the definition of "S" so it is before onRead
4) Use a void pointer: (void*)&s;

Related

Global namespace scope operator on function definition

I am in the process of creating a C wrapper around a C++ library.
One common mistake to make while doing this is having a function declaration and definition that do not match for some reason (typo, renames, argument got added/removed, etc).
For example:
// enabledata.h
MDS_C_API const char* motek_mds_enable_data_get_enable_command_name();
// enabledata.cpp
const char* motek_mds_enable_data_enable_command_name() { ... }
The names do not match, but because of the lack of scope for these functions, it will not result in any compile errors, and will only show up much later down the line as a link error.
I want the compiler to help me find these errors by using the global scope operator like so:
const char* ::motek_mds_enable_data_get_disable_command_name() { ... }
This will now show up as a compile error if the function has not been declared yet, which is exactly what I want.
However, this does not work when the function returns a typedef:
int32_t ::motek_mds_enable_data_is_enabled(const Data* a_Data) { ... }
This will result in an attempt to use int32_t as a scope, which of course results in an error:
left of '::' must be a class/struct/union
Are there any ways to make this work? Better alternatives are also welcome of course.
I am currently using Visual Studio 2015 Update 2.
You can always parenthesize the declarator-id:
int32_t (::motek_mds_enable_data_is_enabled)(const Data* a_Data) { ... }
// ^ ^

Why can't I pass typedef or enum in Arduino?

The following sketch to fails to compile in the Arduino environment.
Given that typedefs can be used within Arduino software, is Automatic Prototype Generation the underlying mechanism that causes the failure? If so, what is it and why isn't Arduino providing a lightweight wrapper around C++?
#define PRODUCE_WACKY_COMPILETIME_ERROR
typedef int MyMeaningfulType;
#ifndef PRODUCE_WACKY_COMPILETIME_ERROR
void myFunc(MyMeaningfulType myParam);
#endif
void myFunc(MyMeaningfulType myParam)
{
myFunc(10);
}
void setup() {}
void loop() {}
For the benefit of the search engines, the errors reported are:
error: variable or field 'myFunc' declared void
error: 'MyMeaningfulType' was not declared in this scope
Please refer to http://arduino.cc/en/Hacking/BuildProcess the specific quote is:
This means that if you want to use a custom type as a function argument, you should declare it within a separate header file.
This page does a good job of explaining how the Arduino Language is different from C/C++ in how it works/pre-processes files.
They are attempting to create prototypes for every function they find. Unfortunately, if you define a typedef in the file before the function, and use that in a function definition, the place they put the function prototype does not see it, and this generates a syntax error.
If you use the 'struct * ' syntax instead in those function definitions, you benefit from C's 'opaque type' facility, in which you can use a struct definition without having it be declared beforehand. So, build the typedef, use it, but use the struct definition in any functions that use the typedef in arguments.
typedef struct mytype_ {
int f1;
} mytype_t;
void myfunc(struct mytype_ * xxx) {
xxx->f1 = 1;
}

Passing Stack to Function

So I'm playing around with stacks and I've filled one in my main function, but now I want to pass it to my other functions so I can traverse through it. I'm not sure what kind of data type to put into the prototype though so that it accepts it. Suggestions? Here's what I have:
Main.cpp
#include <iostream>
using namespace std;
#include "stack.h"
void displayStack(char &stackRef);
int main()
{
Stack<char> stack;
stack.push('a');
stack.push('b');
stack.push('c');
return 0;
};
void displayStack(char starRef)
{
// Cannot Get here - Errors!
};
It's telling me I have too many arguments and it doesn't match argument list.
This should suffice:
void displayStack(const Stack<char>& stack);
The name DisplayStack indicates that the function only displays the stack, not changing it in any way. So then the argument can be a reference to const. However, the suffix Stack in the name is redundant since it is implied by the argument, so I’d do it like this:
#include <iostream>
using namespace std;
#include "stack.h"
typedef Stack< char > CharStack;
void display( CharStack const& stack )
{
// ... Display the stack
}
int main()
{
CharStack stack;
for( auto const ch : { 'a', 'b', 'c' } )
{
stack.push( ch );
}
display( stack );
}
Note that …
The function has been moved above main. No silly pure declaration required then, less work. DRY: Don't Repeat Yourself.
Incorrect semicolons after the function definitions, have been removed. Well, at least I think they’re incorrect. Whether they are or not, they’re totally superfluous.
Superfluous return 0; in main has been removed, because that is the default. However, some programmers prefer to have it explicit.
On the downside, while the C++11 loop compiles nicely with g++ 4.7.2, it causes an Internal Compiler Error (ICE) with Visual C++ 11.0:
[d:\dev\test]
> cl foo.cpp
foo.cpp
foo.cpp(7) : warning C4100: 'stack' : unreferenced formal parameter
foo.cpp(16) : error C2059: syntax error : '{'
foo.cpp(16) : error C2143: syntax error : missing ';' before '}'
c1xx : fatal error C1063: INTERNAL COMPILER ERROR
Please choose the Technical Support command on the Visual C++
Help menu, or open the Technical Support help file for more information
[d:\dev\test]
> _
Oh well.
Do that your way. ;-)
Compiler bug reported to Microsoft.
If you do not want to modify contents of the stack inside the function:
void displayStack(const Stack<char> &starRef)
If you want to modify the contents of the stack inside the function:
void displayStack(Stack<char> &starRef)
Points to note:
The type of the variable being passed must be the type you mention in function prototype.
In C/C++, by default all arguments to function are passed by copy, i.e: A copy of the argument rather than the argument itself is passed to the function. The overhead is the copy. You pass by reference to avoid overhead of a copy of variable being passed.
You use const qualifier on the argument if you want the passed variable to be immutable in the function.
Change your displayStack function to:
void displayStack(Stack<char> &stackRef)

Why does scope of using directive make a difference?

Below are two simplified code examples: the first one compiles just fine, the second one emits a compile error (no operator << found which takes a left hand operator ByteVector...).
The only difference in between the two examples is the placement of the using directive.
I don't want to know why it fails (you got not enough information to answer this), I am only interested in why it does make any difference where I place the using.
I would have expected the exact same behaviour in both examples.
Compiles without error
ByteVector Test()
{
using Base::operator <<;
ByteVector foo;
int bar = 1;
foo << bar;
return foo;
}
Compiles with error
using Base::operator <<;
ByteVector Test()
{
...same as above, without using
}
Extra information:
The operator<< used is defined as follows
template<typename T>
ByteVector& operator<<(ByteVector &, const T&){...};
The only thing that comes to my mind is Visual Studio. If that was the case, you may want to put the using directive right after the corresponding #include. As the remark on the page says:
Putt your using directive at the beginning of the source code file to
reduce the potential for unexpected behavior with IntelliSense.
Otherwise, it shouldn't make any difference.

Checking if a function has C-linkage at compile-time [unsolvable]

Is there any way to check if a given function is declared with C-linkage (that is, with extern "C") at compile-time?
I am developing a plugin system. Each plugin can supply factory functions to the plugin-loading code. However, this has to be done via name (and subsequent use of GetProcAddress or dlsym). This requires that the functions be declared with C-linkage so as to prevent name-mangling. It would be nice to be able to throw a compiler error if the referred-to function is declared with C++-linkage (as opposed to finding out at runtime when a function with that name does not exist).
Here's a simplified example of what I mean:
extern "C" void my_func()
{
}
void my_other_func()
{
}
// Replace this struct with one that actually works
template<typename T>
struct is_c_linkage
{
static const bool value = true;
};
template<typename T>
void assertCLinkage(T *func)
{
static_assert(is_c_linkage<T>::value, "Supplied function does not have C-linkage");
}
int main()
{
assertCLinkage(my_func); // Should compile
assertCLinkage(my_other_func); // Should NOT compile
}
Is there a possible implementation of is_c_linkage that would throw a compiler error for the second function, but not the first? I'm not sure that it's possible (though it may exist as a compiler extension, which I'd still like to know of). Thanks.
I agree with Jonathan Leffler that this probably is not possible in a standard way. Maybe it would be possible somewhat, depending on the compiler and even version of the compiler, but you would have to experiment to determine possible approaches and accept the fact that the compiler's behavior was likely unintentional and might be "fixed" in later versions.
With g++ version 4.4.4 on Debian Squeeze, for example, you might be able to raise a compiler error for functions that are not stdcall with this approach:
void my_func() __attribute__((stdcall));
void my_func() { }
void my_other_func() { }
template <typename ret_, typename... args_>
struct stdcall_fun_t
{
typedef ret_ (*type)(args_...) __attribute__((stdcall));
};
int main()
{
stdcall_fun_t<void>::type pFn(&my_func),
pFn2(&my_other_func);
}
g++ -std=c++0x fails to compile this code because:
SO2936360.cpp:17: error: invalid conversion from ‘void ()()’ to ‘void ()()’
Line 17 is the declaration of pFn2. If I get rid of this declaration, then compilation succeeds.
Unfortunately, this technique does not work with cdecl.
For Unix/Linux, how about analyzing the resulting binary with 'nm' and looking for symbol names? I suppose it's not what you meant, but still it's sort of compile time.