iav*_*avr 5 c++ static-members one-definition-rule constexpr c++11
在下面,static constexpr成员L在类中初始化A,然后通过值或(通用)引用传递.后者在Clang中失败但在GCC中失败,并且成员/非成员函数的行为略有不同.更详细:
#include <iostream>
using namespace std;
struct A
{
static constexpr size_t L = 4;
template <typename T>
void member_ref(T&& x) { cout << std::forward<T>(x) << endl; }
template <typename T>
void member_val(T x) { cout << x << endl; }
};
template <typename T>
void ref(T&& x) { cout << std::forward<T>(x) << endl; }
template <typename T>
void val(T x) { cout << x << endl; }
int main ()
{
A().member_ref(A::L); // Clang: linker error: undefined reference to `A::L'
A().member_val(A::L); // fine (prints 4)
ref(A::L); // Clang: compiles/links fine, no output
val(A::L); // fine (prints 4)
}
Run Code Online (Sandbox Code Playgroud)
经过一些实验,将问题从一个更大的程序中分离出来后,我意识到我不小心使用了一个constexpr变量的地址,尽管我只对这个值感兴趣.
我想传递(通用)引用,以便代码是通用的,并且可以在不复制的情况下使用大型结构.我认为你可以传递任何带有通用引用的东西,但看起来这不是这里的情况.我不能使用单独的(类外)定义,L因为这是仅限标头库的一部分.
因此,一种解决方法可以是在调用时生成一个值,即说size_t(A::L)或类似的东西,A::get_L()而不是在A::L哪里(在类内A)
static constexpr size_t get_L() { return L; }
Run Code Online (Sandbox Code Playgroud)
但这两种解决方案看起来都有点笨拙.在我的实际代码中,调用是在类中进行的,看起来看起来call(0, L, ...)很无辜(0, L看起来像值).我想让电话尽可能简单.
您需要A::L在源文件中的类之外定义
constexpr size_t A::L;
Run Code Online (Sandbox Code Playgroud)
使用 Clang 的实例
对于仅标头代码,如果您的类A还不是模板,您可以定义一个A_<T>具有默认值的类模板,并根据该值void编写 typedefA
template<class = void>
struct A_
{
static constexpr size_t L = 4;
template <typename T>
void member_ref(T&& x) { cout << std::forward<T>(x) << endl; }
template <typename T>
void member_val(T x) { cout << x << endl; }
};
template<class T>
constexpr size_t A_<T>::L;
using A = A_<>;
Run Code Online (Sandbox Code Playgroud)
注意:这项业务可能涉及大量的样板文件。值得注意的是,人们可以写
template
<
class MyConcept1,
class MyConcept2,
class YetAnotherConcept
// more long and well-documented template parameter names
>
struct A
{
// many static constexpr variabels
};
template<class P1, class P2, class P3 /* many more short parameter names */>
constexpr SomeType A<P1, P2, P3, /* many more */>::some_var;
// many more one-liners.
Run Code Online (Sandbox Code Playgroud)
模板参数只有正式名称,它们不必在各处都相同(不过,只需将它们按正确的顺序放置即可!)。
| 归档时间: |
|
| 查看次数: |
884 次 |
| 最近记录: |