小编zjy*_*qs 的帖子

定义模板类相同类型的静态 constexpr 成员

非模板类的类似问题

对于模板类,

template <typename T>
struct Test {
    T data;

    static const Test constant;
};
Run Code Online (Sandbox Code Playgroud)

定义特殊类型的成员变量时没问题static constexpr

template <>
inline constexpr Test<int> Test<int>::constant {42};
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/o4c4YojMf


static constexpr当直接从模板类定义成员而不实例化时,编译器的结果会有所不同:

template <typename T>
inline constexpr Test<T> Test<T>::constant {42};
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/M8jdx3WzM

GCC编译。
clang忽略constexpr定义中的说明符。
MSVC.../std:c++17效果很好,但/std:c++20由于重新定义而被拒绝。


我了解到constexpr可以应用于定义变量或变量模板

在这个例子中,哪一个是正确的?为什么?

c++ language-lawyer c++17 c++20

7
推荐指数
1
解决办法
654
查看次数

为什么使用 ADL 时 `std::ranges::size` 需要非常量方法?

否则,如果 Ranges::disable_sized_range<std::remove_cv_t<T>> 为 false,则 size(t) 转换为其衰减类型,并且转换后的表达式有效且具有类似整数的类型,其中重载解析通过以下命令执行以下候选人:

  • void size(auto&) = delete;
  • void size(const auto&) = delete; 1
class Test {
    friend size_t size(/*const*/ Test&) {
        return 0;
    }
};

int main() {
    std::ranges::size(Test{});
    // no matching function error when adding the `const` qualifier
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/79e5vrKrT


一般来说,方法size不需要std::size.

为什么会有这样的限制呢std::ranges::size?(好像只有非会员版才能执行。)

c++ argument-dependent-lookup c++20 std-ranges

7
推荐指数
1
解决办法
1562
查看次数

调用重载的 &lt;brace-enlinedinitializer list&gt; 对于不可转换的类型是不明确的

相关问题:


问题与12类似,但不一样。


#include <type_traits>
#include <vector>

struct A {
    A();
};
static_assert(std::is_convertible_v<double, A> == false);
static_assert(std::is_convertible_v<A, double> == false);

void func(std::vector<double> values);
void func(std::vector<A> as);

int main() {
    func({ 4.2 });
}
Run Code Online (Sandbox Code Playgroud)

显然,doubleA不能相互隐式转换。所以我觉得void func(std::vector<double>)应该叫。

但不同编译器的结果是不同的: https://godbolt.org/z/c1hW47f4c

GCC 无法编译:

<source>: In function 'int main()':
<source>:14:9: error: call of overloaded 'func(<brace-enclosed initializer list>)' is ambiguous
   14 |     func({ 4.2 });
      |     ~~~~^~~~~~~~~
<source>:10:6: note: candidate: 'void func(std::vector<double>)'
   10 | void func(std::vector<double> …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer braced-init-list

7
推荐指数
1
解决办法
254
查看次数

用户定义的基本类型转换可以删除吗?

template<typename Integral>
struct IntegralWrapper {
    Integral _value;

    IntegralWrapper() = default;

    IntegralWrapper(Integral value)
        : _value(value) {}
    
    operator Integral() const {
        return _value;
    }

    operator bool() const = delete;
};

int main() {
    IntegralWrapper<int> i1, i2;
    i1 * i2;
}
Run Code Online (Sandbox Code Playgroud)

gcc 编译成功,但 MSVC 和 clang 编译失败,错误overloaded operator '*' is ambiguous。问题来自于显式删除operator bool

https://godbolt.org/z/nh6M11d98


哪一方(gcc 或 clang/MSVC)是正确的?为什么?

c++ operator-overloading language-lawyer implicit-conversion

5
推荐指数
1
解决办法
92
查看次数

`pair&lt;Key, Value&gt;` 和 `pair&lt;const Key, Value&gt;` 之间的类型双关

一个相对的问题,但我想要一个没有任何运行时开销的解决方案。(所以构建一个新的pair或使用std::variant不是答案)


由于潜在的模板专业化,参考文献已经说过pair<K, V>pair<const K, V>不相似,这意味着简单的reinterpret_cast会触发未定义的行为。

auto p1 = pair<int, double>{ 1, 2.3 };
auto& p2 = reinterpret_cast<pair<const int, double>&>(p1); // UB!
Run Code Online (Sandbox Code Playgroud)

类型双关union在 C 中工作得很好,但在 C++ 中并不总是合法的:

但有一个例外(与 C 中的行为一致?):

如果两个联合成员是标准布局类型,则在任何编译器上检查它们的公共子序列都是明确定义的。

由于KeyandValue可能不是并且standard-layout可能有non-trivial析构函数,因此这里的类型双关似乎是不可能的,尽管pair<Key, Value>和的成员pair<const Key, Value>可以共享相同的生命周期(当然带有对齐断言)。

template <typename Key, typename Value>
union MapPair {
    using TrueType = pair<Key, Value>;
    using …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer type-punning

5
推荐指数
1
解决办法
194
查看次数

Concepts(C++20) 可以用作布尔值吗?

using T = decltype(std::same_as<int, double>) 我在VS2019上试过这个。事实证明T = bool

这是由标准定义的,还是只是特定编译器的属性?我还没有找到任何有关它的官方信息.. https://en.cppreference.com/w/cpp/concepts

c++ c++-concepts c++20

4
推荐指数
1
解决办法
1259
查看次数

为什么 std::compare_three_way 不是模板结构/函子

例如,比较的std::less定义为模板结构

template< class T = void >
struct less;
Run Code Online (Sandbox Code Playgroud)

Whilestd::compare_three_way被定义为一个普通的结构体,它operator()是一个模板函数。(来自 MSVC 的代码)

struct compare_three_way {
    template <class _Ty1, class _Ty2>
        requires three_way_comparable_with<_Ty1, _Ty2> // TRANSITION, GH-489
    constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
        noexcept(noexcept(_STD forward<_Ty1>(_Left) <=> _STD forward<_Ty2>(_Right))) /* strengthened */ {
        return _STD forward<_Ty1>(_Left) <=> _STD forward<_Ty2>(_Right);
    }

    using is_transparent = int;
};
Run Code Online (Sandbox Code Playgroud)

那么为什么不是std::compare_three_way模板结构呢?

template <class _Ty1, class _Ty2>
    requires three_way_comparable_with<_Ty1, _Ty2>
struct compare_three_way {
    constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) …
Run Code Online (Sandbox Code Playgroud)

c++ c++20

3
推荐指数
1
解决办法
137
查看次数

在 C# 中,x+=y 和 x=x+y(x 和 y 都是简单类型)之间有什么性能差异?

在 C/C++ 中,

复合赋值运算符将简单赋值运算符与另一个二元运算符组合在一起。复合赋值运算符执行附加运算符指定的操作,然后将结果分配给左操作数。例如,复合赋值表达式,如

expression1 += expression2

可以理解为

expression1 = expression1 + expression2

然而,复合赋值表达式并不等同于扩展版本,因为复合赋值表达式只计算 expression1 一次,而扩展版本计算 expression1 两次:在加法运算和赋值运算中。

(引自Microsoft Docs


例如:

  1. 对于i+=2;,i将直接修改而不创建任何新对象。
  2. 对于i=i+2;i首先会创建一个副本。复制的一个将被修改,然后被分配回i.
        i_copied = i;
        i_copied += 2;
        i = i_copied;
Run Code Online (Sandbox Code Playgroud)

如果没有编译器的任何优化,第二种方法将构造一个无用的实例,从而降低性能。


在 C# 中,+=不允许重载类似运算符。并且所有像or一样的简单类型都声明为(这是否意味着 C# 中的所有结构实际上都是不可变的?)。intdoublereadonly struct

我不知道在C#,是有一定的表达力对象被修改(至少对于简单类型)直接,而不被创建的任何无用实例。

而且,是否有可能在C#-compiler优化表达x=x+yx+=y不如预期,如果有一个从构造函数和deconstructors无副作用。

c# operator-keyword

2
推荐指数
1
解决办法
209
查看次数