小编vso*_*tco的帖子

如何初始化constexpr引用

我试图初始化一个constexpr参考没有成功.我试过了

#include <iostream>

constexpr int& f(int& x) // can define functions returning constexpr references
{
    return x;
}

int main()
{
    constexpr int x{20};
    constexpr const int& z = x; // error here
}
Run Code Online (Sandbox Code Playgroud)

但我得到编译时错误

错误:constexpr变量'z'必须由常量表达式初始化

删除const结果

错误:将类型'int'的引用绑定到类型'const int'的值会删除限定符

即使我有一种constexpr自动暗示const变量声明的感觉.

所以我的问题是:

  1. constexpr参考以往有用吗?(即比const参考文献"更好" )
  2. 如果是,我该如何有效地定义它们?

PS:我看过几个与我有关的问题,例如哪些值可以分配给`constexpr`参考?,但我不认为他们解决了我的问题.

c++ reference constexpr c++11

21
推荐指数
3
解决办法
5323
查看次数

C++ 11虚拟析构函数和自动生成移动特殊函数

C++ 11中自动生成特殊移动函数(构造函数和赋值运算符)的规则指定不能声明析构函数.据推测,如果你需要在破坏中做一些特别的事情,那么这一举动可能并不安全.

但是,对于多态中正确的析构函数调用,必须将基类的析构函数声明为虚拟(否则通过其基类的指针删除子类的实例将无法正确链接析构函数).

我假设,即使是一个空的析构函数也会阻止编译器自动生成一个特殊的移动函数.如:

class Base {
    virtual ~Base() { }
};
Run Code Online (Sandbox Code Playgroud)

但是,您可以默认析构函数,如下所示:

class Base {
    virtual ~Base() = default;
}
Run Code Online (Sandbox Code Playgroud)

问题1:这是否允许编译器自动生成特殊的移动函数?

但是,显式默认析构函数存在问题.至少在GCC 4.8.2的情况下,签名被隐式地改为noexcept.如:

class Base {
    virtual ~Base() = default; // compiler changes to:
    // virtual ~Base() noexcept;
}
Run Code Online (Sandbox Code Playgroud)

虽然我在析构函数中使用noexcept没有问题,但这会破坏以下"客户端"代码:

class Sub : public Base {
    virtual ~Sub(); // this declaration is now "looser" because of no noexcept
}
Run Code Online (Sandbox Code Playgroud)

所以问题2更重要的是:有没有办法允许在C++ 11中自动生成特殊的移动函数,并允许正确的析构函数链接到子类(如上所述),所有这些都不会破坏子类("客户端")代码?

c++ inheritance move-semantics c++11

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

使用const char*作为非类型参数的模板技巧

我非常清楚直接传递const char*作为模板的非类型参数是错误的,因为在两个不同的转换单元中定义的两个相同的字符串文字可能具有不同的地址(尽管大多数情况下编译器使用相同的地址).可以使用一个技巧,请参阅下面的代码:

#include <iostream>

template<const char* msg>
void display()
{
    std::cout << msg << std::endl;
}

// need to have external linkage 
// so that there are no multiple definitions
extern const char str1[] = "Test 1"; // (1)

// Why constexpr is enough? Does it have external linkage?
constexpr char str2[] = "Test 2";    // (2)

// Why doesn't this work? 
extern const char* str3 = "Test 3";  // (3) doesn't work

// using C_PTR_CHAR = const …
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr c++11

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

这是转发参考吗?

在这个例子中,Scott Meyers明确了rvalue引用和转发引用之间的区别:

Widget&& var1 = someWidget;     // here, “&&” means rvalue reference (1)

auto&& var2 = var1;             // here, “&&” does not mean rvalue reference (2)

template<typename T>
void f(std::vector<T>&& param); // here, “&&” means rvalue reference (3)

template<typename T>
void f(T&& param);              // here, “&&”does not mean rvalue reference (4)
Run Code Online (Sandbox Code Playgroud)

本质上,当我们有一个可推导的上下文时就会出现这种区别,因此案例(3)明确表明我们有一个,vector<...>&&T案例(4)是要推断的,并且(在应用参考折叠规则之后)按"价值类别"分类.

但是更复杂的模式匹配会发生什么?以下面的情况为例:

template <template <class...> class Tuple, class... Ts>
void f(Tuple<Ts...>&& arg)
{

}
Run Code Online (Sandbox Code Playgroud)

&&这里的意思是什么?

c++ perfect-forwarding c++11 forwarding-reference

20
推荐指数
2
解决办法
2994
查看次数

将函数应用于所有Eigen矩阵元素

我有一个Eigen::MatrixXd,我想通过应用组件功能来修改其所有元素.例如:

MatrixXd m = ...;

for each m[i][j]:
  m[i][j] = exp(m[i][j]);
Run Code Online (Sandbox Code Playgroud)

有没有办法实现这个结果?

c++ matrix eigen

19
推荐指数
3
解决办法
7921
查看次数

我如何使用大小的运算符删除/删除[],为什么它们更好?

C++ 14引入了"大小"版本operator delete,即

void operator delete( void* ptr, std::size_t sz );
Run Code Online (Sandbox Code Playgroud)

void operator delete[]( void* ptr, std::size_t sz );
Run Code Online (Sandbox Code Playgroud)

通过N3536阅读,似乎引入了这些运营商以提高性能.我知道典型的分配器operator new"存储"大容量内存的大小,这就是典型的operator delete"知道"多少内存返回到免费商店.

我不确定为什么"大小"版本operator delete会在性能方面有所帮助.唯一可以加快速度的是从控制块开始减少关于大小的读取操作.这确实是唯一的优势吗?

其次,我该如何处理阵列版本?AFAIK,分配的数组的大小不是简单的sizeof(type)*number_elements,但可能会分配一些额外的字节,因为实现可能会使用这些字节作为控制字节.operator delete[]在这种情况下我应该传递什么"大小" ?你能提供一个简短的使用例子吗?

c++ delete-operator c++14

19
推荐指数
2
解决办法
2281
查看次数

为什么这个SFINAE片段不能用于g ++,而是在MSVC中工作?

在MSVC2017中,这工作正常,两个static_asserts都没有按预期触发:

template <typename T>
struct do_have_size {
    template <typename = decltype(std::declval<T>().size())>
    static std::true_type check(T);
    static std::false_type check(...);
    using type = decltype(check(std::declval<T>()));
};

int main() {
    using TR = typename do_have_size<std::vector<int>>::type;
    using FL = typename do_have_size<int>::type;

    static_assert(std::is_same<TR, std::true_type>::value, "TRUE");
    static_assert(std::is_same<FL, std::false_type>::value, "FALSE");
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我在g ++ 7.1或clang 4.0中编译,我会得到以下编译器错误:

In instantiation of 'struct do_have_size<int>':
20:39:   required from here
9:24: error: request for member 'size' in 'declval<do_have_size<int>::TP>()', which is of non-class type 'int'
Run Code Online (Sandbox Code Playgroud)

根据我对SFINAE的理解,true_type返回函数的替换应该对int参数失败,并且应该选择下一个函数,就像在MSVC中一样.为什么clang和g ++根本没有编译它?

-std=c++17只用开关编译,可能需要更多东西?

c++ templates sfinae c++11

19
推荐指数
3
解决办法
1520
查看次数

指针非类型模板参数

我真的不明白为什么下面的代码不能编译:

template<const char*>
struct Foo{};

constexpr const char s1[] = "test1";
constexpr const char* const s2 = "test2";

int main()
{
    Foo<s1> foo1; // ok
    // Foo<s2> foo2; // doesn't compile
}
Run Code Online (Sandbox Code Playgroud)

取消注释最后一main()行使g ++和clang ++发出错误

error: 's2' is not a valid template argument because 's2' is a
variable, not the address of a variable
Run Code Online (Sandbox Code Playgroud)

error: non-type template argument for template parameter of
      pointer type 'const char *' must have its address taken
Run Code Online (Sandbox Code Playgroud)

分别.

我的问题是:

  1. 为什么s1实例化 …

c++ templates c++11

17
推荐指数
3
解决办法
1594
查看次数

无法从成员变量中的initializer-string中推断出数组大小的原因是什么?

考虑一下代码:

struct Foo
{
    const char str[] = "test";
};

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

它无法使用g ++和clang ++编译,基本上吐出来

error: array bound cannot be deduced from an in-class initializer

我明白这是标准可能会说的,但有什么特别好的理由吗?由于我们有一个字符串文字,似乎编译器应该能够毫无问题地推断出大小,类似于简单地声明一个类外const的类似C的空终止字符串的情况.

c++ c-strings in-class-initialization c++11

17
推荐指数
2
解决办法
3903
查看次数

如何禁止公共继承但允许私有(和受保护)继承

C++ 11引入了关键字final以禁止未来覆盖或禁止继承.可以使用它的最常见示例是针对不打算用作基类的类的情况(具有例如非虚拟析构函数).但是,有时我们可能希望在两个类(即继承)之间建立一个is-implemented-in-terms- between private,而不是is-a关系(public继承).但是,final禁止这两种类型的继承.

我的问题如下:有没有任何方法允许private继承但禁止public继承(可能不是直接,但至少我们可以"模拟"它)?在这种情况下,即使我们使用具有非虚析构函数的类也不会有任何问题,因为我们不能通过指向base的指针直接使用派生类,所以我们应该没问题.

我在考虑这样的代码:

class Base /*final*/ {}; // making it final prohibits both private and public inheritance

class PrivateDerived: private Base{}; // this should work

class PublicDerived: public Base{}; // this shouldn't

int main()
{
    PrivateDerived prvd;
    PublicDerived  pubd; // this should not compile

    // Base* pBase = new PrivateDerived; // doesn't work, so we are ok
}
Run Code Online (Sandbox Code Playgroud)

c++ inheritance c++11

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