以下代码给出了未定义的引用链接错误:
template<int>
struct X {
static constexpr int x = 0;
};
template<>
constexpr int X<1>::x;
int main()
{
return X<1>::x;
}
Run Code Online (Sandbox Code Playgroud)
但我不知道确切的原因。
是否可以在不专门化整个模板的情况下定义数据成员?
需要明确的是:这段代码编译得很好,但会出现链接器错误(未定义引用)。
以下是一个有时生成警卫有时不生成的最小示例:
struct A {
inline A(int v = 0) {} // without ctors, guards are omitted
int m1() const {
return m;
}
private:
int m = 0;
};
//namespace { // without anon-ns guards are generated
template<typename T>
struct X {
static int foo() {
// static T m; // even as local-static and -fno-threadsafe-statics, guards are generated
return m.m1();
}
inline static T m; // comment this and uncomment above to try as local-static
};
//}
int main() …Run Code Online (Sandbox Code Playgroud) 我想使用constexpr bool(useF在下面的示例中)来启用以下代码中的功能.在这里,打电话A::f().另外,我希望在关闭该功能的情况下成为alias-template(a)void.
我试图使用constexpr if语句,但是主体仍在实例化,这会导致编译错误.如果我使用包装器模板(X),正如我预期的那样丢弃了正文,但这对我来说似乎很难看.有没有其他方法可以做到这一点?
constexpr bool useF = false;
struct A {
static void f() {}
};
using a = std::conditional<useF, A, void>::type;
template<typename L>
struct X {
static void h() {
if constexpr(std::is_same<L, A>::value) {
L::f(); // not instantiated, no error
}
}
};
int main() {
if constexpr(useF) {
a::f(); // error!?
}
X<a>::h();
}
Run Code Online (Sandbox Code Playgroud)
我正在使用g ++ - 7.0.1和-std = c ++ 17
这个问题在没有捕获的情况下访问lambda表达式中的constexpr变量回答了为什么下面示例中的ref-capture不是严格必要的.但另一方面,如果被捕获,则会收到错误.
这个错误似乎是由递归本质引发的foo().
template<typename T>
constexpr int bar(const T& x) { // NOK
//constexpr int bar(T x) { // OK
return x;
}
template<typename T>
int foo(const T& l) {
constexpr auto x = l() - 1;
auto y = [&]{return bar(x);}; // if ref-capture is used, the above bar(const T&) is NOK, why?
if constexpr(x <= 0) {
return 42;
}
else {
return foo(y);
}
}
auto l2 = []{
return 3;
};
int main() …Run Code Online (Sandbox Code Playgroud) 为什么不识别以下文字运算符模板?
template<char... Chars>
constexpr int operator"" _p(){
return 0;
}
int main()
{
int fs1 = "123"_p;
}
Run Code Online (Sandbox Code Playgroud)
更新: 感谢我现在使用的答案:
#include <avr/pgmspace.h>
template<typename C, C... CC>
struct PgmString {
static constexpr const char* str(){
return &data[0];
}
static constexpr const char data[] PROGMEM = {CC..., '\0'};
};
template<typename C, C... CC>
constexpr const char PgmString<C, CC...>::data[] PROGMEM;
template<typename C, C... CC>
constexpr PgmString<C, CC...> operator"" _pgm(){
return PgmString<C, CC...>();
}
Run Code Online (Sandbox Code Playgroud)
这会将字符串放入AVR微控制器的闪存中.但是如果我将文字字符串长度增加一个字符,则使用的闪存大小会增加两(!)个字节.
在下面的类模板我想initalize成员阵列b与参数组的值vv在反奥得!
template<typename T>
struct Test {
public:
template<typename... B>
explicit Test(B... vv) : b{vv...,} // how to initialize member b with pack expansion v... in reverse order
{
}
private:
std::byte b[sizeof(T)];
};
Run Code Online (Sandbox Code Playgroud)
我无法想象如何在表单中反转参数包扩展,它也可以在初始化列表中使用。
我尝试使用约束进行类专门化:
struct A {};
struct B {};
struct C {};
template<typename T>
concept bool AorB() {
return std::is_same<T, A>::value || std::is_same<T, B>::value;
}
template<typename T>
class X {};
template<AorB T>
class X {};
int main() {
X<A> x1; // error: redeclaration 'template<class T> class X' with different constraints class X {};
X<B> x2;
X<C> x3;
}
Run Code Online (Sandbox Code Playgroud)
我不知道我在这里犯了错误,或者这一般是不可能的?
有什么可以替代这种方法?我可以使用CRTP到一个公共基本模板的专业化,但这对我来说看起来很难看.
下面是两个大多数相同的模板PgmArray和PgmArrayF.第一个适用于lvalue-ref模板参数,第二个适用于积分参数.我喜欢将这两者合二为一:
#include <stdint.h>
#include <type_traits>
#include <array>
#include <iostream>
template<typename T, const T&... Ts>
struct PgmArray final {
static constexpr uint8_t size = sizeof... (Ts);
static constexpr T data[] {Ts...};
};
template<typename T, T... Ts>
struct PgmArrayF final {
static constexpr uint8_t size = sizeof... (Ts);
static constexpr T data[] {Ts...};
};
struct A{
uint8_t m = 0;
};
constexpr A a1{1};
constexpr A a2{2};
constexpr auto x1 = PgmArray<A, a1, a2>{}; // ok
constexpr auto …Run Code Online (Sandbox Code Playgroud) 在下面的例子中
template<auto V>
struct A {};
struct B {
constexpr B(int a) : value{a} {}
private:
int value{0};
};
int main() {
constexpr B b{0};
A<b> t2;
}
Run Code Online (Sandbox Code Playgroud)
成员value必须是公共的才能使类型B结构化以将其用作 NTTP for A.
那么,没有可以用作 NTTP 的具有私有成员的类型吗?这是http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1907r1.html的真正意图吗?
在 C 语言中,结构化类型的名称S是 ist struct S。
在 C++ 中,也可以用作struct S类型名,而不是像S平常那样使用 for
struct S {};
struct S s1; // also ok in C++
S s2; // normal way in C++
Run Code Online (Sandbox Code Playgroud)
因此,假设在 C++ 中使用struct SorS作为类型名是一个品味问题;-)
但下面的例子中有一些地方struct S是不允许的:
struct S1 {
S1(int x = 0) : x{x} {}
int x{};
};
typedef S1 S2;
template<typename T>
auto foo(T a) {
// T::_; // T is deduced to `S` in all …Run Code Online (Sandbox Code Playgroud) c++ ×10
c++17 ×4
templates ×2
c++-concepts ×1
c++20 ×1
constexpr ×1
constructor ×1
declaration ×1
g++ ×1
gcc ×1
if-constexpr ×1
lambda ×1
literals ×1
static ×1
struct ×1