Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to put using directives in C++ header files

For my project I am using some pretty convoluted data structures, e.g.

std::unordered_map<int, std::list<std::shared_ptr<const Foo>>>

for which I would like to declare type aliases for readability. The code on which I built my project on already did this by putting using statements globally in the header files:

// bar.h
#ifndef BAR_H
#define BAR_H

#include <unordered_map>
#include <list>
#include <memory>
#include "foo.h"

using FooTable = std::unordered_map<int, std::list<std::shared_ptr<const Foo>>>;

class Bar {
    FooTable create_foo();
};

#endif

Since my C++ knowledge was a little rusty, I just adopted this style -- but now I read that using using in that way can be problematic, since it forces this alias on everything that includes this header.

Despite a good amount of googling, I could not find a concrete answer on how to handle this properly, only lots of statements on what not to do. So, I just put the using inside the class:

// bar.h
#ifndef BAR_H
#define BAR_H

#include <unordered_map>
#include <list>
#include <memory>
#include "foo.h"


class Bar {
    using FooTable = std::unordered_map<int, std::list<std::shared_ptr<const Foo>>>;

    FooTable create_foo();
};

#endif

However this has the drawback, that I need to restate the alias in the source file:

// bar.cpp
#include "bar.h"

using FooTable = std::unordered_map<int, std::list<std::shared_ptr<const Foo>>>;

FooTable Bar::create_foo()
{
...
}

While this seems to work, I am not sure whether this is safe... and my gut tells me it is kind of ugly. So before I rewrite my whole project like this I thought I'd ask: Is a there a better/more elegant/safer way to do this? Or should I just refrain from using type aliases in header files completely?

like image 791
Hooloovoo Avatar asked Sep 02 '19 12:09

Hooloovoo


People also ask

What do you put in header files in C?

The header file contains only declarations, and is included by the . c file for the module. Put only structure type declarations, function prototypes, and global variable extern declarations, in the . h file; put the function definitions and global variable definitions and initializations in the .

Which preprocessor directive is used to add header files?

You request to use a header file in your program by including it with the C preprocessing directive “#include”.

Which section of c program contains #include directive?

Usually, every program contains “#” at the top, which is a preprocessor directive that includes files or definitions.


1 Answers

However this has the drawback, that I need to restate the alias in the source file:

That is incorrect. You need only make it public then specify the proper scope, so you'd call it Bar::FooTable outside of the scope of Bar (which includes return types, unless trailing!):

Bar::FooTable Bar::create_foo()
{ /* ... */ }

or

auto Bar::create_foo() -> FooTable
{ /* ... */ }

(Just FooTable is fine within the definition, as it's a member!)

Your approach is fine, though I'd put everything in a namespace too. Then it doesn't really matter whether your alias is in the class or not: it's still self-contained within your own code. It becomes purely a matter of style, with little to no impact on anyone else.

like image 58
Lightness Races in Orbit Avatar answered Oct 08 '22 13:10

Lightness Races in Orbit