c++ - 无 ODR 使用的完美转发

标签 c++ c++14 constexpr perfect-forwarding one-definition-rule

考虑以下代码片段,就像写在头文件中一样:

struct Foo {
    // ...
};

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

我可以用一些参数调用makeFoo,然后返回一个Foo。太好了。

现在我要做的是用标签替换一些makeFoo的参数,看起来就像这样(仍在头文件中):

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

应该在 makeFoo 中检测到这些标签,并在调用 Foo 的构造函数之前替换实际对象。所以调用看起来像:

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

但这里有一个问题:这种声明我的标签的方式非常方便,但是如果我 ODR 使用它们中的任何一个,我需要在其他地方提供一个定义。一点都不方便。

并根据this conveniently specific answer (强调我的):

"the object isn't odr-used" is probably the only questionable condition. Basically, it requires that you don't necessitate the variables runtime existence as a symbol, which in turn implies that

  • You don't bind it to a reference (=> you don't forward it!)
  • [...]

...我真的很困惑。

如何在不使用 ODR 的情况下从参数中筛选出标签,同时完美转发其他参数?

  • “标签”被定义为具有type typedef 的东西。

  • 每个标记声明都由宏 defineTag(name, ActualType) 生成,因此只要它是独立的并且不会改变(太多),就可以改变它调用 makeFoo 的语法。

  • 完全不涉及 ODR 的替代解决方案就可以了。

  • C++17 的内联变量听起来像是救赎,但我想避免为那个单一问题将自己锁定在这个项目的前沿编译器中。

最佳答案

如果您可以更改获取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);

关于c++ - 无 ODR 使用的完美转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42890559/

相关文章:

c++ - fstream 不写入文件

c++ - this 在静态成员函数的未计算上下文中

c++ - 数组的 constexpr 初始化以对内容进行排序

c++ - 使用 consteval 代替 constexpr 函数有什么优点?

c++ - BeautifulSoup 的 C/CPP 版本,特别是在处理格式错误的 HTML 方面

c++ - 安装 Qt 不工作

c++ - std::make_unique<T[]>(size) 值初始化

c++ - cout vector<vector<int>> 更简洁

c++ - 是否可以在 constexpr 中使用 std::string ?

c++ - 与(静态)库的两种方式通信