小编Nat*_*son的帖子

是否可以在允许显式转换的同时弃用隐式转换?

假设我有一个简单的Duration类:

class Duration
{
    int seconds;
public:
    Duration(int t_seconds) : seconds(t_seconds) { }
};

int main()
{
    Duration t(30);
    t = 60;
}
Run Code Online (Sandbox Code Playgroud)

我决定我不喜欢能够从 隐式转换intDuration。我可以制作构造函数explicit

class Duration
{
    int seconds;
public:
    explicit Duration(int t_seconds) : seconds(t_seconds) { }
};

int main()
{
    Duration t(30); // This is fine, conversion is explicit
    t = 60; // Doesn't compile: implicit conversion no longer present for operator=
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我不想立即破坏所有隐式转换为 的调用代码怎么办Duration?我想要的是这样的:

class Duration
{ …
Run Code Online (Sandbox Code Playgroud)

c++ type-conversion

29
推荐指数
1
解决办法
1589
查看次数

有没有办法告诉 Visual Studio 将警告视为警告,而不是错误?

在 Visual Studio 中,警告 C4996(使用不推荐使用的函数)被视为错误,使用不推荐使用的函数的代码根本不会编译。

有多种方法可以完全禁用 C4996,可以为单行、翻译单元或整个项目禁用它。但是如果我希望它仍然发出警告,但允许编译而不将其视为错误怎么办?

#include <iostream>

[[deprecated]]
void deprecated_function()
{
    std::cout << "I function, but have been deprecated.\n";
}

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

这根本无法编译。

#include <iostream>

[[deprecated]]
void deprecated_function()
{
    std::cout << "I function, but have been deprecated.\n";
}

int main() {
#pragma warning(suppress: 4996)
    deprecated_function();
}
Run Code Online (Sandbox Code Playgroud)

这会编译,但根本不会发出警告。

对于已弃用的函数,是否可以告诉 Visual Studio 发出警告,但仍允许编译?我正在考虑重构目的,我想将一个函数标记为已弃用,标识它使用的所有位置,但代码仍在每个中间阶段编译,其中一些但不是所有已弃用函数的用途已被替换。

我正在使用 Visual Studio 2019 Community 16.8.4 进行编译,警告级别设置为 /W3,“将警告视为错误”设置为“否”。如果发出此特定警告,它似乎被视为错误。

c++ compiler-warnings visual-studio visual-c++

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

哪些运算符是为作用域枚举自动定义的?

对于无作用域枚举,答案是“大多数”,因为隐式转换为基础整数类型。但是,作用域枚举没有这种隐式转换。相反,为它们定义了一些但不是所有可用于无作用域枚举的运算符。

#include <iostream>

enum class Color{
    Red,
    Green,
    Blue
};

int main()
{
    std::cout << (Color::Red < Color::Green) << '\n';
    // Fine, operator< is defined for Color
    std::cout << (Color::Red + Color::Green == Color::Green) << '\n';
    // no match for 'operator+'
}
Run Code Online (Sandbox Code Playgroud)

我的猜测是关系运算符已定义,但算术运算符未定义,但我在 cppreference 页面上没有看到任何明确说明的内容,也没有进行实际的标准潜水以了解 C++ 对事情。

c++ enums operators

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

函数可以通过 const 引用 * 不* 接受临时变量作为参数来接受参数吗?

激励示例:

假设我们有一个类Foo和一个ObservesFoo具有指向 a 实例的非拥有指针的类Foo。我们可以这样写:

class Foo {};

class ObservesFoo
{
    Foo* p_foo = nullptr;

    ObservesFoo(Foo* t_foo) : p_foo(t_foo) { }
};
Run Code Online (Sandbox Code Playgroud)

但也许我不认为nullptr这是一个有效的价值p_foo。我可以编写一个不同的构造函数来ObservesFoo强制执行此要求,而无需执行诸如 throw if t_foois invalid 之类的操作:

ObservesFoo(Foo& t_foo) : p_foo(&t_foo) { }
Run Code Online (Sandbox Code Playgroud)

然后我对自己说,“等等,这个构造函数没有改变 t_foo。我不应该把它当作一个const Foo&吗?” 但是,如果我这样编写函数,它可能会接受一个临时Foo参数作为其参数,一旦构造函数返回,其生命周期将立即结束,这将消除我从确保p_foo不是的任何保证nullptr,因为现在它可以非常很容易成为悬垂的指针。

有没有一种干净的方法可以在Foo&构造函数和const Foo&构造函数之间取得中间立场?

c++ reference

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

为什么以 2 位小数精度格式化的 0.125 显示“0.12”而不是“0.13”?

考虑:

#include <iostream>
#include <iomanip>
 
int main()
{
    std::cout << std::fixed << std::setprecision(2);
    std::cout << 0.125 << '\n'; // Prints "0.12"
    std::cout << 0.126 << '\n'; // Prints "0.13" as expected
}
Run Code Online (Sandbox Code Playgroud)

演示

我知道浮点数学并不完全精确,但0.125实际上不是准确表示的值之一吗?为什么格式化时是"0.12"向下舍入而不是向上舍入?"0.13"

c++ floating-point string-formatting

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

为什么 operator==(std::variant&lt;T, U&gt;, T) 不起作用?

考虑以下:

#include <iostream>
#include <variant>

int main ()
{
    std::variant<int, float> foo = 3;
    if(foo == 3)
    {
        std::cout << "Equals 3\n";
    }
}

Run Code Online (Sandbox Code Playgroud)

Godbolt 演示在这里

这不会编译,因为foo == 3

<source>:7:12: error: no match for 'operator==' (operand types are 'std::variant<int, float>' and 'int')
    7 |     if(foo == 3)
      |        ~~~ ^~ ~
      |        |      |
      |        |      int
      |        std::variant<int, float>
In file included from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/iosfwd:40,
                 from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/ios:38,
                 from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/ostream:38,
                 from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/iostream:39,
                 from <source>:1:
/opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/bits/postypes.h:192:5: note: candidate: 'template<class _StateT> …
Run Code Online (Sandbox Code Playgroud)

c++ variant

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

std::array、std::vector 和 std::copy 之间的交互

我正在尝试将 a 复制到usingstd::array中。std::vectorstd::copy

根据cppReference,其原型std::copy为:

std::copy(InputIt first, InputIt last, OutputIt d_first)
Run Code Online (Sandbox Code Playgroud)

,其中OutputIt d_first代表目标范围的开头。

通过遵循实现,我有以下代码:

std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

std::vector<int> vec;

std::copy(arr.begin(), arr.end(), vec.begin());
Run Code Online (Sandbox Code Playgroud)

然而,代码并没有像我预期的那样工作,它只是没有将 复制arrayvector.

根据快速谷歌搜索,代码应该是:

std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

std::vector<int> vec;

std::copy(arr.begin(), arr.end(), std::back_inserter(vec));
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么第一个代码不起作用?

vec.begin()被视为OutputIt d_first,其中我的理解是“代表目的地第一个位置的迭代器”?

c++ arrays containers vector

0
推荐指数
1
解决办法
210
查看次数