小编Jam*_*ree的帖子

在using-declaration中,依赖名称可以在模板替换后呈现给构造函数吗?

在这个例子中:

template<class T>
struct S : T
{
    using T::X;
};
Run Code Online (Sandbox Code Playgroud)

T::X是指部件上的从属名称XT.如果S<T>实例化为T = X:

struct X
{
    X(int) {}
};
...
S<X> s(42);
Run Code Online (Sandbox Code Playgroud)

using声明是否会成为继承构造函数?

Clang拒绝代码DEMO,而g ++接受它.

请注意,如果我们写:

using T::X::X;
Run Code Online (Sandbox Code Playgroud)

两个编译器都接受代码并将其视为继承构造函数.被using T::X允许通过标准成为继承,构造函数?

c++ templates using-declaration language-lawyer inheriting-constructors

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

param-pack上的广义lambda捕获?

在C++ 14中,广义lambda捕获让我们做:

template<class T>
auto pack(T t)
{
    return [t=std::move(t)](auto&& f){f(t);};
};
Run Code Online (Sandbox Code Playgroud)

但它没有玩param-pack:

template<class... T>
auto pack(T... t)
{
    return [t=std::move(t)...](auto&& f){f(t...);};
};
Run Code Online (Sandbox Code Playgroud)

是否有任何特殊语法或进一步的标准提案来解决这个问题?

c++ lambda variadic-functions c++14

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

可以将变量重新声明为推导为相同类型的auto吗?

标准是否允许以下​​内容?

#include <iostream>

extern int a;
auto a = 3;

int main(int, char**)
{
    std::cout << a << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

clang接受代码. g ++抱怨声明冲突.

c++ extern language-lawyer auto c++11

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

`std :: array <T,0>`默认是可构造的,其中`T`不是默认可构造的?

请考虑以下代码:

#include <array>

struct T
{
    T() = delete;
};

int main()
{
    std::array<T, 0> a;
    a.size();
}
Run Code Online (Sandbox Code Playgroud)

我们默认初始化一个0大小的数组.由于没有元素,因此不T应该调用构造函数.

但是,Clang仍然需要T默认构造,而GCC接受上面的代码.

请注意,如果我们将数组初始化更改为:

std::array<T, 0> a{};
Run Code Online (Sandbox Code Playgroud)

Clang这次接受了.

非默认构造是否可以T防止std::array<T, 0>默认构造?

c++ arrays language-lawyer c++11

15
推荐指数
2
解决办法
378
查看次数

涉及非推导参数包的函数指针的参数类型的模板参数推导

这类似于问题,但更具体的情况.这次,没有编译器按预期工作.

template<class T>
struct nondeduced
{
    using type = T;
};

template<class T>
using nondeduced_t = typename nondeduced<T>::type;

template<class... T, class U>
void f(void(*)(nondeduced_t<T>..., U)) {}

void g(int, char) { }

int main()
{
    f<int>(g); // error?
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,T无法推导出参数包,但编译器应该能够U在显式参数替换pack之后推导出T(即int在这种情况下为single ).

预计上述内容也可以在没有nondeduced_t诀窍的情况下工作:

template<class... T, class U>
void f(void(*)(T..., U)) {}
Run Code Online (Sandbox Code Playgroud)

因为T根据[temp.deduct.type] p5,参数包已经在非推导的上下文中

未推断的上下文是:

  • 函数参数包,不会出现在参数声明列表的末尾.

不幸的是,我测试过的编译器(g ++/clang)都没有接受代码.值得注意的是,下面的内容适用于g ++和clang.

template<class... T>
void f(void(*)(nondeduced_t<T>..., char)) {}
Run Code Online (Sandbox Code Playgroud)

而且,这对两者都不起作用:

template<class... …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer variadic-templates c++11 template-argument-deduction

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

是`使用Base :: operator T`允许`T`是模板类型参数?

考虑这个例子:

struct B { operator int(); };

template<class T>
struct X:B
{
    using B::operator T;
};
Run Code Online (Sandbox Code Playgroud)

GCC接受代码,而Clang和MSVC拒绝它.哪个是对的?

请注意,如果基类型是相关的,则所有编译器都接受以下代码:

template<class T>
struct B { operator T(); };

template<class T>
struct X:B<T>
{
    using B<T>::operator T;
};
Run Code Online (Sandbox Code Playgroud)

c++ templates using-declaration conversion-operator

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

NRVO不应该保证本地命名变量和call-site变量采用相同的地址吗?

我认为它应该,因为它对正确性很重要.但是,我很惊讶地看到了Clang的输出.请考虑以下代码:

#include <iostream>

struct S
{
    int i;

    S(int i) : i(i) {}

    S(S&&)
    {
        std::cout << "S(S&&)\n";
    }

    S(S const&) = delete;
};

S f()
{
    S s{42};
    std::cout << &s << "\n";
    return s;
}

int main()
{
    S s{f()};
    std::cout << &s << "\n";
    std::cout << s.i << "\n";
}
Run Code Online (Sandbox Code Playgroud)

我们定义了一个移动ctor S来检查是否S(S&&)被调用,如果没有,则应用NRVO.

我们从GCC看到的结果是:

0x7ffc3ed7b5ac
0x7ffc3ed7b5ac
42
Run Code Online (Sandbox Code Playgroud)

应用NRVO并且它们采用相同的地址,这是预期的.

但是,Clang的输出:

0x7fff908bbcc8
0x7fff908bbcf8
42
Run Code Online (Sandbox Code Playgroud)

应用NRVO但地址不同.

如果你想知道为什么有相同的地址是重要的 - 这是因为某些对象可能在构造时对其地址进行一些注册,如果对象被移动,则应该通知它(例如通过move-ctor).

应用NRVO但具有不同的存储器地址因此使其形成不良.这明显违反了合同 - 没有调用自定义移动/复制ctor,编译器如何将S的数据"复制"到另一个地方?

这是Clang的一个错误吗?


如果我们添加一个析构函数S,例如 …

c++ nrvo

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

auto &&如何延长临时对象的生命周期?

下面的代码说明了我的担忧:

#include <iostream>


struct O
{
    ~O()
    {
        std::cout << "~O()\n";
    }
};

struct wrapper
{
    O const& val;

    ~wrapper()
    {
        std::cout << "~wrapper()\n";
    }
};

struct wrapperEx // with explicit ctor
{
    O const& val;

    explicit wrapperEx(O const& val)
      : val(val)
    {}

    ~wrapperEx()
    {
        std::cout << "~wrapperEx()\n";
    }
};

template<class T>
T&& f(T&& t)
{
    return std::forward<T>(t);
}


int main()
{
    std::cout << "case 1-----------\n";
    {
        auto&& a = wrapper{O()};
        std::cout << "end-scope\n";
    }
    std::cout << "case 2-----------\n";
    { …
Run Code Online (Sandbox Code Playgroud)

c++ temporary lifetime auto c++11

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

成员声明`decltype(name)name;`在本地结构中允许,其中第一个名称是指封闭范围?

例:

int main()
{
    int a = 0;
    struct X
    {
        decltype(a) a;
    };
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

decltype(a)指的是本地amain,而成员,它声明股相同的名称.

Clang编译没有任何问题,MSVC14也是如此.

G ++抱怨它,添加-fpermissive使它通过

prog.cc:6:21: error: declaration of 'int main()::X::a' [-fpermissive]
         decltype(a) a;
                     ^
prog.cc:3:9: error: changes meaning of 'a' from 'int a' [-fpermissive]
     int a = 0;
Run Code Online (Sandbox Code Playgroud)

哪种行为符合标准?

c++ language-lawyer c++11

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

可以使用std :: uintptr_t来避免越界指针算法的未定义行为吗?

现在我们知道,越界 - 指针算术具有未定义的行为,如本SO问题所述.

我的问题是:我们可以通过转换为std :: uintptr_t进行算术运算然后转换回指针来解决这种限制吗?是保证工作吗?

例如:

char a[5];
auto u = reinterpret_cast<std::uintptr_t>(a) - 1;
auto p = reinterpret_cast<char*>(u + 1); // OK?
Run Code Online (Sandbox Code Playgroud)

真实世界的用法是优化偏移内存访问 - 而不是p[n + offset]我想做的offset_p[n].

编辑使问题更明确:

给定一个pchar数组的基指针,如果p + n是一个有效的指针,将reinterpret_cast<char*>(reinterpret_cast<std::uintptr_t>(p) + n)保证产生相同的有效指针?

c++ pointers pointer-arithmetic

7
推荐指数
2
解决办法
1379
查看次数