1

I wanted to know if it was possible to call a void function without using a temp variable. E.g. in the following code block...

#include <iostream>

void earlyInit()
{
  std::cout << "The void before the world." << std::endl;
}

int g_foo = (earlyInit(), 0);

int main( int argc, char* argv[] )
{
  std::cout << "Hello, world!" << std::endl;
}

...I have no need for g_foo and would rather it not exist. Is there a way to call void functions without an intermediate temp variable?

StoneThrow
  • 5,314
  • 4
  • 44
  • 86
  • 1
    You just asked this and deleted it. Why? –  Mar 31 '17 at 22:41
  • Have you considered instead an approach similar to a lazy-loaded Meyers Singleton? – user4581301 Mar 31 '17 at 22:44
  • @NeilButterworth Because I am stupid. Sorry. I am sincerely contrite. – StoneThrow Mar 31 '17 at 22:44
  • @user4581301 I think the design pattern you pointed out would still require static initialization of one singleton object wouldn't it? If not, please post further details. The crux of my question was whether it was possible to call a function before `main()` without a temp variable. – StoneThrow Mar 31 '17 at 22:55
  • 1
    " The crux of my question was whether it was possible to call a function before main() without a temp variable" - the answer is, portably? No. –  Mar 31 '17 at 22:57
  • It's not an answer to your question as asked, but if you put that global variable in a separate compilation unit and put it in an anonymous namespace (or declared it `static`), it would have the same effect. – jamesdlin Mar 31 '17 at 23:19
  • @StoneThrow yes it would I wasn't thinking of cases where you would want a single shot init time call that had side effects like send a packet to X rather than the usual get a handle sense. – user4581301 Apr 01 '17 at 00:18

3 Answers3

1

I wanted to know if it was possible to call a void function without using a temp variable. E.g. in the following code block.

The language does not provide any such mechanism. As other answers have pointed out, there maybe compiler-specific ways to do that.

However, I don't see anything wrong with your approach. I use the following pattern a lot.

#include <iostream>

namespace mainNS  // A file-specific namespace.
{
   void earlyInit()
   {
      std::cout << "The void before the world." << std::endl;
   }

   struct Initializer
   {
      Initializer();
   };
}

using namespace mainNS;
static Initializer initializer;

Initializer::Initializer()
{
   earlyInit();
   // Call any other functions that makes sense for your application.
}

int main( int argc, char* argv[] )
{
  std::cout << "Hello, world!" << std::endl;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

An answer to this question brought __attribute__((constructor)) to my attention, however, for reasons I don't fully understand, I observed a SIGSEGV when using that if the void function used std::cout (printf did not cause the SIGSEGV).

I posted a version of this question earlier (but stupidly deleted it). An answerer at that time pointed me to this excellent article which discusses the situation and solution:

http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html

Excerpt of the solution (modified slightly to pass compilation) is here:

#include <cstdio>
#include <cstdlib>

void preinit(int argc, char * * argv, char * * envp) {
  printf("%s\n", __FUNCTION__);
}
void init(int argc, char * * argv, char * * envp) {
  printf("%s\n", __FUNCTION__);
}

void fini() {
  printf("%s\n", __FUNCTION__);
}
__attribute__((section(".init_array"))) typeof (init) * __init = init;
__attribute__((section(".preinit_array"))) typeof (preinit) * __preinit = preinit;
__attribute__((section(".fini_array"))) typeof (fini) * __fini = fini;

void __attribute__((constructor)) constructor() {
  printf("%s\n", __FUNCTION__);
}

void __attribute__((destructor)) destructor() {
  printf("%s\n", __FUNCTION__);
}

void my_atexit() {
  printf("%s\n", __FUNCTION__);
}

void my_atexit2() {
  printf("%s\n", __FUNCTION__);
}

int main() {
  atexit(my_atexit);
  atexit(my_atexit2);
}

(Apologies to the original answerer that I deleted my original post and can't give due credit.)

Community
  • 1
  • 1
StoneThrow
  • 5,314
  • 4
  • 44
  • 86
0

Check if your compiler supports #pragma startup (or equivalent), eg:

#include <iostream>

void earlyInit()
{
  std::cout << "The void before the world." << std::endl;
}
#pragma startup earlyInit

int main( int argc, char* argv[] )
{
  std::cout << "Hello, world!" << std::endl;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Looked promising, but my compiler doesn't seem to support this. Nor did Code Chef. To which compiler(s) is this an extension? – StoneThrow Mar 31 '17 at 23:04
  • @StoneThrow: which compiler are you actually using? Different compilers support different things. bcc supports `#pragma startup`, VC++ supports `#pragma init_seg`, gcc and clang support `__attribute__((constructor))`. And so on. That is why I said "(or equivalent)" in my answer. – Remy Lebeau Mar 31 '17 at 23:38
  • g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7). Don't make fun of me! I know it's old, but it's out of my control. – StoneThrow Mar 31 '17 at 23:48