Can C++ inline function call function declared later in the header? - c++

The following works just-fine in MSVC2008 and MSVC2010:
class Foo {
public:
static void FuncA(void) {
FuncB(); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
static void FuncB(void);
};
Yes, this is kinda weird: FuncA() calls FuncB(), even though (at that point) FuncB() is not-yet-declared. However, MSVC2008 and MSVC2010 thinks this is fine.
Apparently, gcc doesn't think this is fine -- FuncB was not declared in this scope.
ISSUE: I have a bunch of these, and it would be a "pain" to declare them, and later define them. Further, it would be hard to "order" them properly so each only calls functions after those were declared. But, I'm guessing I need to declare-first-then-define-later?
Are the rules different for whether these functions are template-or-not, or defined within a template-class or not?
Specifically, I've noticed Microsoft is very "late-compiling" where it accepts tons of inter-coupled code, and LATER resolves (at compile, when the template-parameterization is triggered), while gcc seems to want to compile now when it "sees" the code (an initial pass for correctness, and again during parameterization/invocation).
(This problem shows up as we port our Microsoft code to Linux/gcc.)
===UPDATE===
The following are "alternate" scenarios that we have (in this code-porting effort), and would your answer change based on any of these?
// Alternate-Scenario-B
class Foo2 {
public:
template<typename SOME_TYPE>
static void FuncA(const SOME_TYPE& some_type) {
FuncB(some_type); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
template<typename SOME_TYPE>
static void FuncB(const SOME_TYPE& some_type);
};
...and:
// Alternate-Scenario-C
template<typename SOME_TYPE>
class Foo3 {
public:
static void FuncA(const SOME_TYPE& some_type) {
FuncB(some_type); // "FuncB()" NOT DECLARED YET? WORKS, MSVC2008
}
static void FuncB(const SOME_TYPE& some_type);
};
===UPDATE+2===
Thanks for the comments, where consensus seems that this is valid C++ code, and should work (as #Adam suggested, a function "defined-inline" should behave as if it were defined after the class, and should be able to call functions defined in the class interface after that inline definition).
MORE INFORMATION:
Yes, I really have this compile error from the first example in the FuncA() inline implementation:
'FuncB' is not a member of 'Foo'
...using:
gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
(Recall that this works on MSVC2008/MSVC2010).
I realize now that my code-example (above) is insufficient (the above example does not show this error on gcc), here are some more details:
Foo has a base-class (I don't think that should matter)
Foo defines an internal enum which is passed through these funcs (I don't think this matters)
these functions are "expanded" through a macro (I think significant -- see below)
there are fifty-six (56) of these functions (I think significant -- see below)
A more complete code example would be (and I am not proud of this):
#define FOO_FUNCS(CLASS_NAME,CLASS_ENUM) \
static void FuncA(CLASS_ENUM value_enum) { \
FuncB(value_enum); /*PROBLEM*/ \
} \
static void FuncB(CLASS_ENUM value_enum) { \
FuncC(value_enum); \
} \
/*...THERE ARE 56 FUNCS IN THIS MACRO, THREE LINES EACH...*/
class Foo : public FooParent {
public:
enum FooEnum { FOO_ONE, FOO_TWO };
FOO_FUNCS(Foo,FooEnum) // EXPAND THE 56 FUNCS
};
CODE INTENT: The FooParent base class has implementation that is intended to be "shared" by (many) derived classes. The derived classes define their own enum values. Functions that used these enum values were implemented through a macro (because the FooParent is not a template<>, and cannot rely upon the derived-enum).
Curious behavior:
If the FooA(){FooB();} nesting references a function defined "later" by only a "few-lines", then gcc compiles fine. However, if the yet-to-be-declared function is much later, like Foo2(){Foo53();}, then gcc concludes that Foo53() is not a member of the class (but it is).
Here's what I think is going on:
There seems to be an issue with lots-of-code (for 56 functions) that are physically on "one-line". If I take these functions out of the macro, AND if I remove \ escape-line-endings, then gcc compiles fine.
Thus, I think the (code-porting) answer is:
don't use a preprocessor-macro
make a FooParentBase<> template class derived from FooParent, from which we derive Foo, which requires the typename Foo::enum as a template-parameter
I'm fine with these changes (I didn't like the macro), but I find it weird that gcc seems to have an issue here.
Are there other suggestions for how to fix this? (Is the above re-factoring what you would do?)

All three of your scenarios are correct and compile with both g++ and clang.

Your code looks perfectly legal to me. Inline definitions within a class definition are supposed to be treated equivalent to declarations with an inline definition immediately following the class definition (by which time the declaration of FuncB() would be available).
My version of GCC accepts this code as valid (all three examples you post, assuming I provide trivial implementations of each FuncB(), of course).
~$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
...
I believe more information is needed here. Perhaps post your version of GCC and the specific error message you're seeing.
========REPLY TO LATER UPDATE=======
I've tried your latest example with 70 functions in the macro, and it's still working for me in gcc 4.6.3. Here is the test I tried (with the macro shortened in the obvious way):
#include <iostream>
using std::cout;
struct FooParent {
static void Func71( int ) {
cout << "Called\n";
}
};
#define FOO_FUNCS(CLASS_NAME,CLASS_ENUM) \
static void Func1(CLASS_ENUM value_enum) { \
Func2(value_enum); /PROBLEM/ \
} \
static void Func2(CLASS_ENUM value_enum) { \
Func3(value_enum); \
} \
/* Functions Func3...Func69 snipped */ \
static void Func70(CLASS_ENUM value_enum) { \
Func71(value_enum); \
} \
/...THERE ARE 70 FUNCS IN THIS MACRO, THREE LINES EACH.../
class Foo : public FooParent {
public:
enum FooEnum { FOO_ONE, FOO_TWO };
FOO_FUNCS(Foo,FooEnum) // EXPAND THE 70 FUNCS
};
int main() {
Foo::Func1(Foo::FOO_ONE);
}

Related

C++ macro value that behaves differently in function vs class/namespace scope

I am trying to define a macro that behaves differently when used in a function context vs a class body or namespace. The purpose of this is to selectively include BOOST_LOG_NAMED_SCOPE (or achieve equivalent behavior) in the LOG_CONTEXT macro referenced here.
I have tried two approaches:
Using BOOST_PP_IF along with a preprocessor function to test whether e.g. __func__ is non-empty.
The output of g++ -E on a basic source file still contains the literal text __func__ in both global and function scope so that probably rules out any approach targeting the preprocessing phase.
Using something like sizeof(__func__) to select a specialized template that implements behavior similar to BOOST_LOG_NAMED_SCOPE. I can re-use the boost::log::attributes::named_scope::sentry object from boost log, but I'm stuck trying to figure out how to instantiate it conditionally in a function context, or at least in a way that works everywhere. The following construction seems to work fine in class definitions and functions, but fails with a "multiple definition" error when linking together multiple translation units that include a header with a LOG_CONTEXT at global or namespace scope:
#include <boost/log/attributes/named_scope.hpp>
#include <type_traits>
namespace logging {
namespace attrs = boost::log::attributes;
namespace detail {
// Default no-op on construction when not in a function.
template<typename ScopeTraits, bool InFunction>
class named_scope_helper
{};
// Specialization when in a function.
template<typename ScopeTraits>
class named_scope_helper<ScopeTraits, true> :
public attrs::named_scope::sentry
{
public:
named_scope_helper() BOOST_NOEXCEPT
: sentry(
ScopeTraits::scope_name(),
ScopeTraits::filename(),
ScopeTraits::lineno() )
{}
};
template<size_t N>
class not_1 : public std::true_type
{};
template<>
class not_1<1> : public std::false_type
{};
#define LOGGING_LOG_IN_FUNCTION \
::logging::detail::not_1<sizeof(__func__)>::value
} // namespace detail
} // namespace logging
// scope_name_t/filename_t are required since attrs::named_scope::sentry
// requires string literals.
#define LOG_CONTEXT( name_ ) \
struct __logging_log_scope_traits__ \
{ \
using scope_name_t = const char (&)[sizeof(name_)]; \
static scope_name_t scope_name() \
{ return name_; } \
using filename_t = const char (&)[sizeof(__FILE__)]; \
static filename_t filename() \
{ return __FILE__; } \
static size_t lineno() \
{ return __LINE__; } \
}; \
::logging::detail::named_scope_helper< \
__logging_log_scope_traits__, LOGGING_LOG_IN_FUNCTION> \
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_log_named_scope_sentry_);
My normal workaround for this would be to use static in the declaration of the _log_named_scope_sentry_, but that defeats the purpose.
I could add another macro that is strictly for non-execution contexts, but wanted to investigate this approach first since it would be an interesting trick to have. How can I proceed on one of the two approaches I've started above, or is there another option I haven't considered?
A general solution would be preferred but I'm only really concerned with GCC and Clang.

Is there a macro or provision to check is the line of code is inside a class?

I have a c style macro in my code, which prints the logs. I want to alter the macro to print the this pointer. But, there are some portion of a code, which is not a member function of a class or some are static functions. So, in my macro I want to check, the current line of code is inside a member function or not. Possible?
No. The preprocessor, as the name says, runs first. Interpreting a sequence of tokens as a class definition is done by the compiler, which runs after the preprocessor. Therefore the preprocessor has no idea about classes, or functions, or variables, or any other C++ construct.
BTW, inside a class you still have static methods that don't have this pointers either.
Well, this doesn't exactly fit your demands but it may be doable to integrate that in a build environment. (Edit: I just realize that it fails for static member functions; hm.)
My idea is to define a function log() twice: one is in the global namespace; it is the obvious result of name resolution for calls from within freestandig functions. The other log() is a member function of a base class from which all classes which want to log must inherit. (That's the bad thing; for a big existing code base that's hardly doable.) The inheritance, function definitions and calls can be made dependent on a preprocessor define so that they have no influence on production code:
#include<cstdio>
// The following would go in a header which must be included by all source
// files which use one of the macros, i.e. which want to log errors.
#ifdef DEBUG
# define INHERIT_LOG() : virtual protected logT
# define LOG(s) log(s)
/** ::log which will be called by free-standing functions */
static void log(const char *err, const void *thisP = nullptr)
{
if(thisP) { fprintf(stderr, "this=%p: %s\n", thisP, err); }
else { fprintf(stderr, "free func: %s\n", err); }
}
/** A base class to inherit from when logging is required */
class logT
{ // this name "log" will be preferred over ::log
// from within all classes which inherit from logT.
protected: void log(const char *const err){ ::log(err, this); }
};
#else
// define the macros to do nothing
# define INHERIT_LOG()
# define LOG(s)
#endif
////////////// end of log header ///////////////
/** Inherits from logT only when DEBUG is defined */
struct T INHERIT_LOG() { void f(); };
void T::f() { LOG("message from T::f"); }// if LOG is expanded to log, calls logT::log
void f() { LOG("message from ::f"); } // if LOG is expanded to log, calls ::log
int main()
{
T().f();
f();
}
Sample session:
$ g++ -std=c++14 -Wall -o log log.cpp && ./log
$ g++ -DDEBUG -std=c++14 -Wall -o log log.cpp && ./log
this=0xffffcc00: message from T::f
free func: message from ::f
$
AFAIK this is not easily possible. There are no ways to check if a variable is defined or not in the preprocessor.
You can introduce a new logic (like inserting something into each
function which defines it type), but it is probably much easier
to have two of your macros for the case if this is defined or not.

Cleanly suppress gcc's `final` suggestion warnings (`-Wsuggest-final-types` and `-Wsuggest-final-methods`)

I like compiling my code using -Wsuggest-final-types and -Wsuggest-final-methods in order to be warned about opportunities where the final keyword could be used to allow the compiler to optimize more aggressively.
Sometimes, though, the suggestions are incorrect - for example, I have a class Base with a virtual ~Base() destructor that is used polymorphically in another project, and gcc suggests me that Base could be marked as final.
Is there a way to "cleanly" tell the compiler that Base is used polymorphically and should not be marked as final?
The only way I can think of is using #pragma directives, but I find it makes the code cluttered and hard to read.
Ideally, I'm looking for a non-final keyword or attribute that can be prepended/appended to the class/method declaration.
I came up with a macro-based solution that I really don't like, but it solves the problem.
#define MARK_NONFINAL_CLASS(base) \
namespace SOME_UNIQUE_NAME \
{ \
struct [[unused]] temp_marker final : base \
{ \
}; \
}
#define MARK_NONFINAL_METHOD(base, return_type, method) \
namespace SOME_UNIQUE_NAME \
{ \
struct [[unused]] temp_marker final : base \
{ \
inline return_type [[unused]] method override {} \
}; \
}
Usage:
class Base
{
virtual ~Base()
{
}
virtual int a(float f)
{
}
virtual void b(double)
{
}
};
MARK_NONFINAL_CLASS(Base)
MARK_NONFINAL_METHOD(Base, int, a(float))
MARK_NONFINAL_METHOD(Base, void, b(double))
Allow me to make a suggestion (and this is how I solved these warnings problems).
The GCC documentation says:
For example -Wsuggest-final-types is more effective with link-time optimization and some instances of other warnings may not be issued at all unless optimization is enabled.
So, to not show this warnings anymore, simply add the link time optimization feature to your command line.
gcc -flto

std::string & as template parameter and abi_tag in gcc 5

Consider the following piece of code (test1.cpp):
#include <string>
extern std::string test_string;
template<std::string &s>
class test{
public:
static void bar(){ }
};
std::string test_string("test string");
void foo(){test<test_string>::bar();}
Now let us switch order of two last lines of code (test2.cpp):
#include <string>
extern std::string test_string;
template<std::string &s>
class test{
public:
static void bar(){ }
};
void foo(){test<test_string>::bar();}
std::string test_string("test string");
Nothing should change. But if you look via objdump to compiled file you will see difference:
objdump -t -C test*.o | grep bar
In one case template test was instantiated as:
test<test_string[abi:cxx11]>::bar()
and in another as:
test<test_string>::bar()
both files are compiled just with
gcc -c test*.cpp
So reference to std::string as template parameter is treated as not tagged if it is just declared extern. And it is treated as tagged after definition.
Some classes in my project are instantiated twice where there should be just one class. It is rather unpleasant.
gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)
Is it a bug in compiler? Or is it expected behavior?
What can be a workaround?
This is definitely a compiler bug; I can't find the exact bug in GCC Bugzilla but it appears similar to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66971 - though simpler, as it doesn't require the use of thread_local keyword, it may well have the same underlying cause.
As a workaround, it appears that changing the reference template parameter to a pointer will make it work:
template<std::string *s> class test { .... };
void foo(){test<&test_string>::bar();}
Edit: I've filed this bug with gcc as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69621

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.