小编Evg*_*Evg的帖子

在VS2017中不是编译时常量表达式

VS2017 15.1无法编译以下代码:

template<int data_size>
struct Data { };

template<int s>
struct Base
{
    static constexpr int size() { return s; }
};

template<int s>
struct Derived : Base<s>   // struct Derived
{
    Data<Base<s>::size()> data;
};

int main()
{
    Derived<1> c;
}
Run Code Online (Sandbox Code Playgroud)

错误是:

error C2975: 'data_size': invalid template argument for 'Data', expected compile-time constant expression
note: see declaration of 'data_size'
note: see reference to class template instantiation 'Derived<s>' being compiled
Run Code Online (Sandbox Code Playgroud)

如果我不是从中衍生Derived出来的Base,那么错误就会消失.使用gcc 5.4.0和clang 4.0.0在这两种情况下一切都很好.

这段代码有什么问题吗?

c++ templates constexpr c++11 visual-studio-2017

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

tuple_map应该返回什么?

我想实现一个带有仿tuple_map函数的泛型函数,并将仿函数std::tuple应用于此元组的每个元素并返回std::tuple结果.实现非常简单,但问题出现了:这个函数应返回什么类型?我的实现使用了std::make_tuple.然而,在这里 std::forward_as_tuple建议.

更具体地说,实现(为简洁起见,省略了对空元组的处理):

#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>

template<class Fn, class Tuple, std::size_t... indices>
constexpr auto tuple_map_v(Fn fn, Tuple&& tuple, std::index_sequence<indices...>)
{
    return std::make_tuple(fn(std::get<indices>(std::forward<Tuple>(tuple)))...);
    //          ^^^
}

template<class Fn, class Tuple, std::size_t... indices>
constexpr auto tuple_map_r(Fn fn, Tuple&& tuple, std::index_sequence<indices...>)
{
    return std::forward_as_tuple(fn(std::get<indices>(std::forward<Tuple>(tuple)))...);
    //          ^^^
}

template<class Tuple, class Fn>
constexpr auto tuple_map_v(Fn fn, Tuple&& tuple)
{ 
    return tuple_map_v(fn, std::forward<Tuple>(tuple), 
        std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}

template<class Tuple, class Fn>
constexpr …
Run Code Online (Sandbox Code Playgroud)

c++ stdtuple c++17

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

右值,左值和形式定义

人们听到他们的声音感到困惑

int&& x
Run Code Online (Sandbox Code Playgroud)

x具有右值引用类型,但x为左值。误解源于标识符和表达式是不同的事物,类型和值类别也是如此。此外,表达式的类型“在进行任何进一步分析之前已调整”,并且单词“ rvalue”和“ lvalue”可以同时出现在类型名称和值类别名称中。

我想澄清正式定义。假设我们有一个函数:

1 | void f(int&& x) {           
2 |     ... = x;               
3 |     ... = std::move(x);
4 | }
Run Code Online (Sandbox Code Playgroud)

以下陈述正确吗?

  1. 在第1行中,x是一个标识符(id表达式),它为函数参数命名。其类型为int&&,这是decltype(x)返回的类型。x不是表达式,没有值类别。
  2. 第2行x是一个表达式。在类型调整之前,其类型为int&&,而在类型变为之后int。值类别为左值。
  3. 在第3行中,std::move(x)是一个表达式。调整前的类型是int&&-之后int。值类别为xvalue。
  4. 当我们说它x具有右值引用类型时,在类型调整之前,我们将其x称为标识符,或者将其x称为表达式。
  5. cppreference.com上的语句“每个表达式都有一些非引用类型,每个表达式恰好属于三个主要值类别之一”中的单词“类型” 是指类型调整后的类型。
  6. 当斯科特·迈耶斯 Scott Meyers)写道: “如果表达式的类型是左值引用(例如T&const T&,等等),则该表达式是左值。” 他是指调整前的类型,第二个单词“左值”是指值类别。

c++ reference language-lawyer c++11 value-categories

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

隐藏的朋友:声明和定义

安东尼·威廉姆斯在他最近的博客文章中谈到了隐藏的朋友。如果我理解正确的话,主要思想是在某些情况下 ADL 无法找到声明为友元的函数。简单的例子:

namespace N {
    struct A {
        friend void foo(A) { }
    };

    struct B {
        operator A();
    };

    // (*)
    void bar(A) { }
}

void func() {
    N::A a;
    bar(a);   // OK, bar is found via ADL
    foo(a);   // OK, foo is found via ADL

    N::B b;
    bar(b);   // OK, bar is found via ADL
    foo(b);   // NOT OK, foo cannot be found
}
Run Code Online (Sandbox Code Playgroud)

在博客文章的所有示例中,友元函数都是在类内定义的。是否可以声明一个友元函数,然后在该点定义它(*),以便它保持隐藏状态?看起来隐藏的朋友只能在类范围(或另一个编译单元)中定义。

c++ friend argument-dependent-lookup

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

静态 constexpr 成员变量初始化

我有以下代码:

struct Foo
{       
    struct Bar
    {
        std::uint32_t x = -1;

        constexpr Bar(std::uint32_t x) : x(x) {}
    };

    static constexpr Bar CONST_BAR = Bar(0);
};
Run Code Online (Sandbox Code Playgroud)

当我尝试编译它时,出现以下错误:

错误:'constexpr Foo::Bar::Bar(uint32_t)' 在定义完成之前在常量表达式中调用

有人可以向我解释发生了什么吗?据我所知,Bar 的构造函数是在第一次调用之前定义的。

活生生的例子

c++ constexpr c++14

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

Lambda的C ++三元赋值

知道为什么以下代码段无法编译吗?它报错“错误:?的操作数:具有不同的类型”

  auto lambda1 = [&](T& arg) {
      ...
  };
  auto lambda2 = [&](T& arg) {
      ...
  };
  auto lambda = condition ? lambda1 : lambda2;
Run Code Online (Sandbox Code Playgroud)

c++ lambda conditional-operator c++11

11
推荐指数
5
解决办法
197
查看次数

不合格的 sort()——为什么在 std::vector 上使用而不是在 std::array 上编译,哪个编译器是正确的?

当调用std::sort()a 时std::array

#include <vector>
#include <array>
#include <algorithm>

int main() {
    std::vector<int> foo{4, 1, 2, 3};
    sort(begin(foo), end(foo));

    std::array<int, 4> foo2{4, 1, 2, 3};
    sort(begin(foo2), end(foo2));
}
Run Code Online (Sandbox Code Playgroud)

gcc 和 clang 都在排序上返回错误std::array-- clang 说

错误:使用未声明的标识符“排序”;你的意思是'标准::排序'?

更改以std::sort(begin(foo2), end(foo2))解决问题。

MSVC 按照编写的方式编译上面的代码。

为什么std::vector和之间的待遇不同std::array;哪个编译器是正确的?

c++ c++17

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

为什么在 gcc 的 is_nothrow_constructible 实现中需要 static_cast?

取自 GCC 实现type_traits为什么static_cast需要这里?

template <typename _Tp, typename... _Args>
struct __is_nt_constructible_impl
    : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))> {};

template <typename _Tp, typename _Arg>
struct __is_nt_constructible_impl<_Tp, _Arg>
    : public integral_constant<bool,
                               // Why is `static_cast` needed here?
                               noexcept(static_cast<_Tp>(declval<_Arg>()))> {};
Run Code Online (Sandbox Code Playgroud)

c++ libstdc++ static-cast type-traits

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

在MSVC中折叠表达式

我有以下函数来计算平均值:

template<typename... Ts>
auto mean_of(const Ts... values)
{
    return (... + values) / static_cast<double>(sizeof...(Ts));
}
Run Code Online (Sandbox Code Playgroud)

使用VS 2017 15.6.0预览3以下代码

std::cout << mean_of(1, 3);
Run Code Online (Sandbox Code Playgroud)

输出2.5.似乎MSVC将折叠表达式解释为1 + 3 / N而不是(1 + 3) / N.如果我在fold表达式周围添加额外的括号,结果是正确的.使用GCC不需要额外的括号.

这是MSVC中的错误还是我们需要额外的括号?

c++ language-lawyer variadic-templates fold-expression c++17

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

自动非类型模板参数:Clang中模棱两可的局部专业化

铛(7,8,主干)拒绝以下代码

enum class E {};
inline static constexpr auto e = E{};
// inline static constexpr auto e = nullptr;

template<auto, int> class S;
template<int a, int b> class S<a, b> {};
template<int b> class S<e, b> {};

int main() {
    S<0, 0> s;
}
Run Code Online (Sandbox Code Playgroud)

带有错误:

error: ambiguous partial specializations of 'S<0, 0>'
note: partial specialization matches [with a = 0, b = 0]
template<int a, int b> class S<a, b> {};
                             ^
note: partial specialization matches [with b = …
Run Code Online (Sandbox Code Playgroud)

c++ templates clang auto c++17

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