【发布时间】:2017-03-19 18:38:00
【问题描述】:
考虑下面的sn-p,好像写在头文件里:
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(强调我的):
“该对象没有被 odr-used” 可能是唯一有问题的条件。基本上,它要求您不必将变量运行时作为符号存在,这反过来意味着
- 你没有将它绑定到一个参考(=>你没有转发它!)
- [...]
...我确实在泡菜。
如何在不使用 ODR 的情况下从参数中筛选出标签,同时完美转发其他参数?
-
“标签”被定义为具有
typetypedef 的东西。 -
每个标记声明都由宏
defineTag(name, ActualType)生成,因此只要它是独立的并且不会(过多)改变对makeFoo的调用的语法,就可以更改它。 -
完全不关心 ODR 的替代解决方案也可以。
-
C++17 的内联变量听起来像是救命稻草,但我想避免因为这个单一问题而将自己锁定在该项目的前沿编译器中。
【问题讨论】:
-
Eric Niebler 的
__static_const疯狂基本上是穷人的内联变量。
标签: c++ c++14 constexpr perfect-forwarding one-definition-rule