小编dfr*_*fri的帖子

什么是标准名称?

据我所知,标准中没有提及“ 完全合格 ”一词(例如),但我可以记得在网上多次“听到”它。

人们说一个名字完全合格是什么意思?

这算吗?

A::f()
Run Code Online (Sandbox Code Playgroud)

还是只有这个?

::A::f()
Run Code Online (Sandbox Code Playgroud)

而且,如果这标准的,我找不到哪个措辞?

c++ language-lawyer c++17

43
推荐指数
2
解决办法
2429
查看次数

lambda 表达式是合法的默认(非类型模板)参数吗?

以下所有标准参考均指N4861(2020 年 3 月布拉格后工作草案/C++20 DIS)


背景

在问答中 无捕获的 lambda 是结构类型吗?很明显,某些 lambda 表达式具有关联的闭包类型,这些闭包类型是(文字和)结构类型,因此特定的此类闭包类型可以用作非类型模板参数;本质上将结构类型 lambda 作为非类型模板参数传递。

template<auto v>
constexpr auto identity_v = v;

constexpr auto l1 = [](){};
constexpr auto l2 = identity_v<l1>;
Run Code Online (Sandbox Code Playgroud)

现在,根据[expr.prim.lambda.closure]/1 ,每个 lambda 表达式的类型都是唯一的

[...] 一个独特的、未命名的非联合类类型,称为闭包类型[...]

另一方面,[basic.def.odr]/1 [extract,强调我的]指出

任何翻译单元不得包含任何变量、函数、类类型、枚举类型、模板、参数的默认参数(对于给定范围内的函数)或默认模板参数的多个定义

可以说,默认模板参数被认为是需要尊重 ODR 的定义。

...这引出了我的问题:

  • lambda 表达式是否是合法的默认(非类型模板)参数,如果是,这是否意味着使用这种默认参数的每个实例化都会实例化一个独特的特化?

(如果接近非法,也请强调:例如,如果超出单个实例化的任何事情都会导致 ODR 违规)。


为什么?

如果这实际上是合法的,则每次调用带有 lambda 作为默认参数的变量模板都会导致唯一特化的实例化:

template<auto l = [](){}>
               // ^^^^^^ - lambda-expression as …
Run Code Online (Sandbox Code Playgroud)

c++ lambda templates language-lawyer c++20

33
推荐指数
1
解决办法
767
查看次数

Swift 3.0迭代String.Index范围

使用Swift 2.2可以实现以下功能:

let m = "alpha"
for i in m.startIndex..<m.endIndex {
    print(m[i])
}
a
l
p
h
a
Run Code Online (Sandbox Code Playgroud)

使用3.0,我们收到以下错误:

类型'范围'(又名'范围')不符合协议'序列'

我试图用swift中的字符串做一个非常简单的操作 - 只是遍历字符串的前半部分(或更普遍的问题:遍历字符串的范围).

我可以做以下事情:

let s = "string"
var midIndex = s.index(s.startIndex, offsetBy: s.characters.count/2)
let r = Range(s.startIndex..<midIndex)
print(s[r])
Run Code Online (Sandbox Code Playgroud)

但在这里,我并没有真正遍历字符串.所以问题是:如何遍历给定字符串的范围.喜欢:

for i in Range(s.startIndex..<s.midIndex) {
    print(s[i])
}
Run Code Online (Sandbox Code Playgroud)

swift swift3

25
推荐指数
4
解决办法
3万
查看次数

通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分特化

以下所有标准参考均指N4659:2017 年 3 月后 Kona 工作草案/C++17 DIS


考虑以下片段:

#include <type_traits>

template <int N> struct num {};

template <typename> struct A;

// (1)
template <int N> struct A<num<N>> { using type = bool; };

// (2)
template <long N> struct A<num<N>> { using type = char; };

static_assert(!std::is_same_v<long, int>, "");

// (A)
static_assert(std::is_same_v<A<num<1>>::type, bool>, "");

int main() {}
Run Code Online (Sandbox Code Playgroud)

static_assert(A)是成功的GCC,但失败了锵:

error: static_assert failed due to 
       requirement 'std::is_same_v<char, bool>' ""
Run Code Online (Sandbox Code Playgroud)

本质上,GCC 选择完美匹配的专业化(1),而 Clang 选择专业化(2) …

c++ language-lawyer

13
推荐指数
1
解决办法
274
查看次数

使用std :: enable_if作为templ时的默认模板参数.param.:为什么两个模板函数只在enable_if参数中有所不同?

cppreference语言参考中std::enable_if包括以下注释

笔记

一个常见的错误是声明两个仅在默认模板参数上有所不同的函数模板.这是非法的,因为默认模板参数不是函数模板签名的一部分,并且声明具有相同签名的两个不同函数模板是非法的.

在下面的示例中的模板函数中,在我看来,这种情况发生.即,两个模板函数onlyForDerivedObjects(...)似乎(对我来说)仅由它们的默认模板参数不同.我意识到我在这里遗漏了一些东西,希望有人可以向我解释这一点,或者指出我可能会为自己找到顿悟的方向.

  • 问题:上面的引用,为什么下面的例子编译并运行正常:typename std::enable_if ...当我认为它产生两个模板函数的情况时,我在下面的模板函数中错误分类了部分,这两个模板函数的区别仅在于它们的默认模板参数?

基础和派生类:

class BaseA
{
public:
  int getInt() const { return 21; };
};

class DerivedA : public BaseA {};

class BaseB
{
public:
  int getAnotherInt() const { return 33; };
};

class DerivedB : public BaseB {};
Run Code Online (Sandbox Code Playgroud)

具有以下模板功能

/* template functions that, seemingly, only differ in their
   default template arguments? */
template< class T,
          typename std::enable_if<std::is_base_of<BaseA, …
Run Code Online (Sandbox Code Playgroud)

c++ templates enable-if c++11

11
推荐指数
2
解决办法
959
查看次数

复合开关案例:对于具有相同类型关联值的复合枚举案例,我们是否可以使用单个公共值绑定?

(当我准备并几乎写完问题时,重新阅读相应的语言指南部分为我解答了,但可能Q&A可能对其他人有用,所以我会发布它)

背景

请考虑以下enum情况,其中包含两种不同类型的关联值之一,Int或者String:

enum Foo {
    case bar(Int)
    case baz(Int)
    case bax(Int)
    case fox(String)
}
Run Code Online (Sandbox Code Playgroud)

switch语句中执行模式匹配时,我们可以构造复合案例,每个案例都包含几种可能的匹配模式(case如果任何模式匹配则进入分支):

func foo(_ foo: Foo) -> Int {
    switch foo {
        case .bar, .baz, .bax: return 42
        case .fox: return 0
    }
}
Run Code Online (Sandbox Code Playgroud)

就像非复合案例一样,复合案例也可能包含价值绑定:

func foo(_ foo: Foo) -> Int {
    switch foo {
        case .bar(let x), .baz(let x), .bax(let x): return x 
        case .fox(let y): return Int(y) ?? 0
    }
}

// or
func …
Run Code Online (Sandbox Code Playgroud)

enums switch-statement swift

11
推荐指数
1
解决办法
1704
查看次数

非final类不能满足协议要求,因为它在非参数非结果类型中使用"Self"

我想用一个类方法实现一个协议,该方法将实现类的数组作为参数.例如这样的事情:

protocol MyProtocol {
    static func foo(verticies: [Self]) -> Int
}

class MyClass : MyProtocol {
    class func foo(verticies: [MyClass]) -> Int {
        return 42
    }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试这个时,我收到以下错误:

协议'MyProtocol'要求'foo()'不能被非最终'MyClass'类满足,因为它在非参数非结果类型中使用'Self'

但是如果我使用MyClass类型的对象而不是数组,这可以很好地工作:

protocol MyProtocol {
    static func foo(verticies: Self) -> Int
}

class MyClass : MyProtocol {
    class func foo(verticies: MyClass) -> Int {
        return 42
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么这不适用于数组类型,并且有正确的方法吗?

swift

10
推荐指数
1
解决办法
5909
查看次数

非类模板中数据成员 std::array 的编译时间大小 (C++14)

编译时检查 std::array 数据成员的(编译时)大小

我需要静态地断言该类型的非constexpr数据成员的编译时大小std::array,比方说arr_,一个的非模板类是等于给定的(外部提供的)恒定。静态断言将从类内部完成,这意味着arr_可以访问,但我不能依赖任何存储的常量(也不是非类型模板参数)的大小。即,断言需要完全依赖于arr_数据成员的“一些检查” 。

如果constexpr std::array<>::size()/std::array<>::max_size()是静态成员函数(decltype(arr_)::size()/ decltype(arr_)::max_size())而不是非静态成员函数,我基本上会完成。

我有一种在成员的指向数据成员的指针上使用函数模板参数推导的工作方法arr_,但我想知道是否有更简单/更整洁的方法。

#include <array>
#include <cstddef>

// Defined/provided from elsewhere.
constexpr std::size_t kArraySize = 12U;
constexpr std::size_t kAnotherArraySize = 12U;

template <typename T, typename U, std::size_t N>
constexpr std::size_t size_of_data_member_array(std::array<T, N> U::*) {
    return N;
}

class Foo {
    std::array<int, kArraySize> arr_;
    static_assert(size_of_data_member_array(&Foo::arr_) == kAnotherArraySize, "");
};

int main() {}
Run Code Online (Sandbox Code Playgroud)

c++ templates stdarray c++14

10
推荐指数
2
解决办法
169
查看次数

约束成员函数和显式模板实例化

G++ 和 Clang++ 同意以下代码段不是有效的 C++:

template<int dim, int rank>
struct Tensor {};

template<int dim>
double InnerProduct(Tensor<dim, 1> const &, Tensor<dim, 1> const &)
  { return 0.0; }

template<int dim>
double DoubleInnerProduct(Tensor<dim, 2> const &, Tensor<dim, 2> const &)
  { return 0.0; }

template<int dim, int rank>
class Field
{
private:
  static double Dot(Tensor<dim, rank> const &u, Tensor<dim, rank> const &v) requires (rank == 1)
    { return InnerProduct(u, v); }

  static double Dot(Tensor<dim, rank> const &u, Tensor<dim, rank> const &v) requires …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer explicit-instantiation c++-concepts c++20

9
推荐指数
1
解决办法
267
查看次数

是否需要一个实现来诊断同一 TU 内同一显式专业化的重复定义的 ODR 违规?

考虑一个模板化实体,比如说(A)一个函数模板,和(B)一个类模板的成员枚举。

// (A)
template<auto>
int f();

// (B)
template <auto>
struct T { enum class E; };
Run Code Online (Sandbox Code Playgroud)

由于此类模板实体的相同显式专业化的重复定义,是否需要实现来诊断 ODR 违规?或者,换句话说,[basic.def.odr]/1 是否适用于显式专业化?


例如,GCC 和 Clang 都将以下程序诊断为格式错误:

// Single translation unit;
// primary template of 'f' declared as in (A) above.
template<>
int f<0>() { return 0; }

template<>
int f<0>() { return 1; }  
  // GCC & Clang - error: redefinition of 'int f() [with auto <anonymous> = 0]'
Run Code Online (Sandbox Code Playgroud)

而只有 Clang 将以下程序诊断为格式错误,而 GCC 接受它:

// Single translation unit;
// …
Run Code Online (Sandbox Code Playgroud)

c++ templates one-definition-rule template-specialization language-lawyer

9
推荐指数
1
解决办法
110
查看次数