C++20尝鲜:非类型模板参数变化

C++20尝鲜:非类型模板参数变化非类型模板形参中的类类型非类型模板参数现在可以是文字类类型(可以用作constexpr变量的类型),所有基类和非静态成员都是公共的和不可变的(字

大家好,欢迎来到IT知识分享网。

非类型模板形参中的类类型

非类型模板参数现在可以是文字类类型(可以用作constexpr变量的类型),所有基类和非静态成员都是公共的和不可变的(字面上,不应该有可变的说明符)。此类类的实例存储为const对象,甚至可以调用它们的成员函数。有一种新的非类型模板形参:派生类类型的占位符。

#include <iostream>
#include <string>
#include <stdio.h>

template<std::size_t N>
struct fixed_string{
    constexpr fixed_string(const char (&s)[N+1]) {
        std::copy_n(s, N + 1, str);
    }
    constexpr const char* data() const {
        return str;
    }
    constexpr std::size_t size() const {
        return N;
    }
    char str[N+1];
};

template<std::size_t N>
fixed_string(const char (&)[N])->fixed_string<N-1>;

// user-defined literals are also supported
template<fixed_string S>
constexpr auto operator""_cts(){
    return S;
}

// N for `S` will be deduced
template<fixed_string S>
void f(){
    std::cout << S.data() << ", " << S.size() << '\n';
}

int main()
{
    f<"abc">(); // abc, 3
    constexpr auto s = "def"_cts;
    f<s>();     // def, 3
    return 0;
}
C++20尝鲜:非类型模板参数变化

在线测试

https://wandbox.org/nojs/gcc-head
https://wandbox.org/nojs/clang-head

泛型非类型模板参数

非类型模板参数被广义为所谓的结构类型。结构类型为:

  • 标量类型(算术、指针、成员指针、枚举、std::nullptr_t)
  • 具有以下属性的左值引用
  • 文字类类型:所有基类和非静态数据成员都是公共的和不可变的,它们的类型是结构类型或数组类型。
    这允许使用浮点和类类型作为模板形参:
#include <iostream>
#include <string>
#include <stdio.h>

template<auto T>    // placeholder for any non-type template parameter
struct X{};

template<typename T, std::size_t N>
struct Arr{
    T data[N];
};

int main()
{
    X<5> x1;
    X<'c'> x2;
    X<1.2> x3;
    // with the help of CTAD for aggregates
    X<Arr{{1,2,3}}> x4; // X<Arr<int, 3>>
    X<Arr{"hi"}> x5;    // X<Arr<char, 3>>

    return 0;
}

这里有趣的是,非类型模板参数不是与它们的操作符==()进行比较,而是以类似位的方式进行比较(确切的规则在这里)。也就是说,它们的位表示用于比较。联合是例外,因为编译器可以跟踪它们的活动成员。如果两个联合都没有活动成员或具有相同值的活动成员,则两个联合是相等的。

#include <iostream>
#include <string>
#include <stdio.h>
#include <assert.h>
#include <string.h>

template<auto T>
struct S{};

union U{
  int a;
  int b;
};

enum class E{
  A = 0,
  B = 0
};

struct C{
  int x;
  bool operator==(const C&) const{    // never equal
    return false;
  }
  };

int main()
{
  constexpr C c1{1};
  constexpr C c2{1};
  assert(c1 != c2);                           // not equal using operator==()
  assert(memcmp(&c1, &c2, sizeof(C)) == 0);   // but equal bitwise
  // thus, equal at compile-time, operator==() is not used
  static_assert(std::is_same_v<S<c1>, S<c2>>);

  constexpr E e1{E::A};
  constexpr E e2{E::B};
  // equal bitwise, enum's identity isn't taken into account
  assert(memcmp(&e1, &e2, sizeof(E)) == 0);
  static_assert(std::is_same_v<S<e1>, S<e2>>); // thus, equal at compile-time

  constexpr U u1{.a=1};
  constexpr U u2{.b=1};
  // equal bitwise but have different active members(a vs. b)
  assert(memcmp(&u1, &u2, sizeof(U)) == 0);
  // thus, not equal at compile-time
  static_assert(!std::is_same_v<S<u1>, S<u2>>);
  return 0;
}

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/61002.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信