Perfect forwarding without using ODR

Consider the following snippet as if it were written in the header file:

struct Foo {
    // ...
};

template <class... Args>
Foo makeFoo(Args &&... args) {
    return {std::forward<Args>(args)...};
}

I can call makeFoowith some parameters and return a Foo. Fine.

Now what I want to do is replace some of the arguments with makeFootags that look the same (still in the header file):

constexpr struct tag_type { using type = ActualType; } tag;

These tags must be discovered internally makeFooand replaced with actual objects before calling the constructor Foo. So the call will look like this:

auto myFoo = makeFoo("hi", ::tagBar, 42, ::tagBaz);

But here's the catch: this way of declaring my tags is very convenient, but if I use ODR using any of them, I need to give a definition somewhere else. Not very convenient.

And in accordance with this convenient specific answer (my attention):

" odr", , . , , , , , ,

  • (= > !)
  • [...]

... .

ODR, , ?

  • "" , type typedef.

  • defineTag(name, ActualType), , ( ) makeFoo.

  • , ODR, .

  • ++ 17 , .

+4
4

type, makeFoo, , :

template <typename> struct tag_helper;

enum { tagBar }; template <> struct tag_helper<decltype(tagBar)> { using type = Bar; };
enum { tagBaz }; template <> struct tag_helper<decltype(tagBaz)> { using type = Baz; };

auto myFoo = makeFoo("hi", ::tagBar, 42, ::tagBaz);
+4

constexpr ?

constexpr struct tag_type { using type = ActualType; };

constexpr tag_type tag() { return {}; }

:

auto myFoo = makeFoo("hi", ::tagBar(), 42, ::tagBaz())

:

constexpr struct tag { using type = ActualType; };

:

auto myFoo = makeFoo("hi", ::tagBar{}, 42, ::tagBaz{})
+1

?

template <class T>
struct tag_t { using type = T; };

template <class T>
constexpr tag_t<T> tag{};

:

auto myFoo = makeFoo("hi", ::tag<Bar>, 42, ::tag<Baz>);
+1

, constexpr static?

Presumably, the Foo constructor is only interested in type, so having multiple tag type models is not significant.

#include <utility>

struct Foo {
    template<class...Args>
            Foo(Args&&...args)
    {}

    // ...
};

template <class... Args>
Foo makeFoo(Args &&... args) {
    return {std::forward<Args>(args)...};
}

struct Bar {};
struct Baz {};

static constexpr struct tagBar_type { using type = Bar; } tagBar {};
static constexpr struct tagBaz_type { using type = Baz; } tagBaz {};

int main()
{
    auto myFoo = makeFoo("hi", ::tagBar, 42, ::tagBaz);
}
0
source

Source: https://habr.com/ru/post/1672682/


All Articles