小编for*_*818的帖子

T 是否必须是一个完整的类型才能在 `std::declval<T>` 中使用?

考虑这个例子(来自这里):

#include <type_traits>
#include <iostream>
template <typename U>
struct A {
};

struct B {
   template <typename F = int>
   A<F> f() { return A<F>{}; }

   using default_return_type = decltype(std::declval<B>().f());
};

int main()
{
    B::default_return_type x{};
    std::cout << std::is_same< B::default_return_type, A<int>>::value;
}
Run Code Online (Sandbox Code Playgroud)

在 gcc9.2 上编译没有错误,但 gcc7.2 和 clang 10.0.0 抱怨B不完整。Clangs 错误是:

prog.cc:11:58: error: member access into incomplete type 'B'
   using default_return_type = decltype(std::declval<B>().f());
                                                         ^
prog.cc:7:8: note: definition of 'B' is not complete until the …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer incomplete-type declval

12
推荐指数
2
解决办法
583
查看次数

假设相同的lambda表达式有不同的类型是否安全?

我正在尝试lambdas以及不同的lambda表达式具有不同类型的事实,即使它们是相同的.考虑这段代码

#include <iostream>

template <typename T> void once(T t){
    static bool first_call = true;
    if (first_call) t();
    first_call = false;
}

int main() {    
    int counter = 0;
    auto a = [&counter](){counter++;};
    once(a);
    once(a);
    std::cout << counter;              // 1

    auto b = a;                        // same type
    once(b);
    std::cout << counter;              // 1

    auto c = [&counter](){counter++;}; // different type
    once(c);
    once(c);               
    std::cout << counter;              // 2
}
Run Code Online (Sandbox Code Playgroud)

此打印112,即,ab是相同类型的,当然和c具有不同的类型.

是否允许编译器使用c的类型与a …

c++ optimization lambda language-lawyer

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

std::array 的地址是否保证与其数据相同?

std::array是...(引用自cppreference):

该容器是一个聚合类型,其语义与将 C 样式数组T[N]作为其唯一非静态数据成员的结构体具有相同的语义。

这是否意味着数组的地址始终与其第一个元素的地址相同,即data()

#include <array>
#include <iostream>

int main()
{
    std::array<int,6> x{};
    std::cout << &x << "\n";
    std::cout << x.data();
}
Run Code Online (Sandbox Code Playgroud)

可能的输出:

0x7ffc86a62860
0x7ffc86a62860
Run Code Online (Sandbox Code Playgroud)

如果是的话,这有什么用吗?允许以下行为吗?

int* p = reinterpret_cast<int*>(&x);
for (int i=0;i<6;++i){ std::cout << p[i]; }
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer stdarray

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

将false转换为指针类型void*?

有人能解释我这里发生了什么......?

我有这个代码:

#include <fstream>
#include <string>
#include <iostream> 
int main(){   
    std::ifstream file("test.txt");    
    std::string x;
    while (true) { 
        if (!(file >> x)) return 0;
        std::cout << x << "\n";   
    }
}
Run Code Online (Sandbox Code Playgroud)

...编译好,做它应该做的,到目前为止没问题.有时候,我不喜欢!这么多,因为它可以很容易被忽略,所以我取代了if

if ((file >> x)==false) return 0;  
Run Code Online (Sandbox Code Playgroud)

..突然我的编译器(gcc 4.8.5)抱怨警告:

 warning: converting ‘false’ to pointer type ‘void*’ [-Wconversion-null]
     if ((file >> x)==false) return 0;
Run Code Online (Sandbox Code Playgroud)

这就是我开始感到困惑的地方.哪里void*来的?不>>返回应该转换为的引用bool吗?为什么false转换成void*?为什么在我不明确写的时候会触发相同的警告false

出于好奇,我也尝试了这个:

if ((file>>x)==true) return 0;
Run Code Online (Sandbox Code Playgroud)

从而引发一场错误风暴

error: no match for …
Run Code Online (Sandbox Code Playgroud)

c++ boolean stream type-conversion

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

是否有 C++14 替代 C++20 中引入的显式(expr)?

TL;DR:我正在寻找与以下 C++20 MWE 等效的 C++14:

template<int sz>
struct bits {
  int v; // note explicit(expr) below
  explicit(sz > 1) operator bool() const { return bool(v); }
};

int main() {
  bool c = bits<1>{1}; // Should work
  bool d = bits<3>{1}; // Should fail
}
Run Code Online (Sandbox Code Playgroud)

语境:

bits<sz>我们有一个表示长度为位向量的C++ 类sz。过去,对 all 的转换bool是隐式的sz,但事实证明这很容易出错,因此我们改为operator bool()显式转换。

然而,1-bit位向量(在我们的上下文中)几乎完全等同于布尔值,因此当 时最好是operator bool()隐式的sz == 1

explicit(sz > 1)这可以在C++20中实现,但我们的目标是 C++14。

我尝试重载 …

c++ implicit-conversion template-meta-programming c++14 c++20

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

C++ 在模块中“使用”

头文件中“使用命名空间”被认为是不好的做法的原因之一(为什么“使用命名空间 std;”被认为是不好的做法?)是因为它将 using 指令“泄露”给包含头文件的每个人。C++ 模块仍然是这种情况吗?或者我可以“安全地”将 例如using namespace stdusing std::cout放入我的模块中吗?:

module;
#include <iostream>
export module Module;

using namespace std;
// using std::cout;
export void greet() {
    cout << "Hello World!\n";
}
Run Code Online (Sandbox Code Playgroud)

c++ c++20

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

bar(type (&amp;)[x]) 定义与 bar(type (&amp;)[x]) 声明不匹配?

这是对成员声明中模板类类型别名失败替换的跟进

考虑这个代码:

// A
template <typename T>
struct foo {
    using type = unsigned;
   
    template <type x>
    void bar(type (&)[x]);
};
    
template <typename T>
template <typename foo<T>::type x>
void foo<T>::bar(type (&)[x]){}
Run Code Online (Sandbox Code Playgroud)

gcc 发出以下错误:

<source>:13:6: error: no declaration matches 'void foo<T>::bar(foo<T>::type (&)[x])'
   13 | void foo<T>::bar(type (&)[x]){}
      |      ^~~~~~
<source>:8:10: note: candidate is: 'template<class T> template<unsigned int x> void foo<T>::bar(foo<T>::type (&)[x])'
    8 |     void bar(type (&)[x]);
      |          ^~~
<source>:4:8: note: 'struct foo<T>' defined here
    4 | struct …
Run Code Online (Sandbox Code Playgroud)

c++ templates language-lawyer

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

为什么我要在这种情况下使用智能指针?

我从来没有使用任何类型的智能指针,但当主题是指针时,我几乎无处不在地阅读它们.我知道有些情况下智能指针比原始指针更好用,因为在某种程度上它们可以管理指针的所有权.但是,我仍然不知道,"我不需要智能指针"和"这是智能指针的情况"之间的界限.

可以说,我有以下情况:

class A {
public:
    double get1(){return 1;}
    double get2(){return 2;}
};
class SomeUtilityClass {
public:
    SomeUtilityClass(A* a) : a(a) {}
    double getResult(){return a->get1() + a->get2();}
    void setA(A* a){a = a;}
private:
    A* a;
};
int main(int argc, char** argv) {
    A a;
    SomeUtilityClass u(&a);
    std::cout << u.getResult() << std::endl;
    A a2;
    u.setA(&a2);
    std::cout << u.getResult() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这当然是一个过于简单的例子.我的意思是SomeUtilityClass不应该"拥有"一个实例A(因为它只是一个实用类),因此它只是一个指针.

关于指针,我所知道的唯一可能出错的是:

  • SomeUtilityClass 可以使用空指针进行实​​例化
  • 指向的对象可能被删除/超出范围,没有SomeUtilityClass注意到它

智能指针如何帮助避免这个问题?在这种情况下,使用智能指针可以获得哪些其他好处?

PS:我知道智能指针有几个问题(例如这个).但是,如果您能告诉我有关此特定示例的影响,我将不胜感激.

c++ pointers smart-pointers

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

没有朋友授予访问私有构造函数的权限?

我正在编写一些代码,在那里我遇到了类似于这个的情况:

struct Bar;

struct Foo{
    friend struct Bar;
private:
    Foo(){}
    void f(){}
    void g(){}
};

struct Bar {
   Foo* f;
   Bar()  { f = new Foo();}
   ~Bar() { delete f;}
};

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

我宁愿Bar不作为friendFoo,因为除了Foo构造函数Bar不需要访问任何的Foo私有方法(因此不应该有访问).有没有办法只允许Bar创建Foos而不让他们成为朋友?

PS:意识到问题可能不是100%清楚.我不介意它是否是通过朋友,只是所有人Bar都可以访问所有私人方法的事实令我感到不安(这通常是这种情况friends),这就是我想要避免的.幸运的是,到目前为止,没有一个答案与这个糟糕的表述有问题.

c++ constructor private friend

8
推荐指数
2
解决办法
385
查看次数

reinterpret_cast vs严格别名

我正在阅读有关严格别名的内容,但它仍然有点模糊,我无法确定定义/未定义行为的界限.我发现最详细的帖子集中在C.所以如果你能告诉我这是否允许以及自C++ 98/11以来发生了什么变化,那将是很好的...

#include <iostream>
#include <cstring>

template <typename T> T transform(T t);

struct my_buffer {
    char data[128];
    unsigned pos;
    my_buffer() : pos(0) {}
    void rewind() { pos = 0; }    
    template <typename T> void push_via_pointer_cast(const T& t) {
        *reinterpret_cast<T*>(&data[pos]) = transform(t);
        pos += sizeof(T);
    }
    template <typename T> void pop_via_pointer_cast(T& t) {
        t = transform( *reinterpret_cast<T*>(&data[pos]) );
        pos += sizeof(T);
    }            
};    
// actually do some real transformation here (and actually also needs an inverse)
// ie this …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing language-lawyer reinterpret-cast

8
推荐指数
2
解决办法
974
查看次数