小编Ant*_*ier的帖子

静态constexpr:为什么需要模板化?

我有两个结构ab:

struct a {
    static constexpr int f() {
        return 1;
    }

    static constexpr int c = f();
};

template<int I>
struct b {
    static constexpr int f() {
        return I;
    }

    static constexpr int c = f();
};
Run Code Online (Sandbox Code Playgroud)

a显然不起作用,因为f这里没有定义.但为什么地狱b有效呢?

c++ constexpr c++14

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

GLSL memoryBarrierShared()有用吗?

我想知道memoryBarrierShared的用处.

实际上,当我查看屏障功能的文档时:我读到:

对于计算着色器中任何给定的屏障静态实例,单个工作组中的所有调用必须在允许任何调用继续超出它之前输入.这确保了在调用相同的屏障静态实例之后,其他调用可以安全地读取在给定静态屏障实例之前由一次调用写入的值.因为调用可能在这些屏障调用之间以未定义的顺序执行,所以在许多情况下,每顶点或每个补丁输出变量或任何共享变量的值将是未定义的.

因此,如果我们可以在使用障碍后安全地读取值,为什么我们会在一些代码中看到

memoryBarrierShared();
barrier();
Run Code Online (Sandbox Code Playgroud)

或者像错误的东西

barrier();
memoryBarrierShared();
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:如果使用障碍足够,memoryBarrier {Shared,...}的目的是什么?

对于memoryBarrierBuffer/Image我可以理解,如果我们使用多个阶段,但对于共享,我不知道...

opengl glsl compute-shader

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

MSVC和constexpr的功能参数?

这段代码用clang和gcc编译得很好.

template<size_t n>
struct N {
    static constexpr size_t v = n;
};

template<size_t n>
constexpr bool operator<(N<n>, size_t n2) {
    return n < n2;
}

template<typename N>
constexpr void foo(N v) {
    static_assert(v < 5);
}

int main()
{
    foo(N<3>{});
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用MSVC,我得到的错误v < 5不是常量表达式.我能理解为什么MSVC会这么想,但我认为这是错误的,而clang/gcc是对的.这是来自MSVC的错误吗?

c++ language-lawyer constexpr c++11

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

SFINAE:知道功能是否已存在或不存在

基本上,我想编写这样的代码:

std::vector<float> a = { 54, 25, 32.5 };
std::vector<int> b = { 55, 65, 6 };

std::cout << a << b << std::string("lol");
Run Code Online (Sandbox Code Playgroud)

这是不可能的,因为没有过载 operator<<(ostream&, vector)

所以,我编写了一个完成这项工作的函数:

template<template<typename...> typename T, typename ...Args>
std::enable_if_t<is_iterable_v<T<Args...>>>, std::ostream> &operator<<(std::ostream &out, T<Args...> const &t) {
    for (auto const &e : t)
        out << e << " ";
    out << std::endl;
    return out;
}
Run Code Online (Sandbox Code Playgroud)

这很好用,但我的字符串有问题.因为字符串是可迭代的,字符串HAVE operator<<功能.

所以我测试了另一个特性,比如!is_streamable_out && _is_iterable测试类似的东西:std::declval<std::ostream&>() << std::declval<T>()如果它有开始/结束功能.它适用于MSVC,但不适用于Clang(我认为这是因为编译器使用我刚刚创建的函数,因此它为所有方法找到了一个可用的重载).

所以,我目前正在使用,!is_same_v<string, T>但它不是完美的恕我直言.

有没有办法知道函数是否存在而不重新声明函数?

基本上,我想做那样的事情

if function foo …
Run Code Online (Sandbox Code Playgroud)

c++ sfinae c++11

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

C++ constexpr:在编译时计算std数组

我想将"数组"转换bool为整数序列.所以我需要std::array在编译时计算一个.

这是我的代码

#include <array>

template<typename InputIt, typename T >
inline constexpr typename std::iterator_traits<InputIt>::difference_type
count( InputIt first, InputIt last, const T &value ) {
    typename std::iterator_traits<InputIt>::difference_type ret = 0;
        for (; first != last; ++first) {
            if (*first == value) {
                ret++;
            }
        }
        return ret;
}

template<bool ..._values>
struct keep_value {
    static constexpr std::size_t numberOfValues = sizeof...(_values);
    static constexpr bool values[] = {_values...};
    static constexpr std::size_t numberToKeep = count(values, values + numberOfValues, true);

    static constexpr std::array<std::size_t, …
Run Code Online (Sandbox Code Playgroud)

c++ template-meta-programming variadic-templates constexpr c++14

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

非多态类型的Dynamic_cast

我可以理解为什么dynamic_cast在这种情况下有效:

#include <iostream>

struct A{
    virtual ~A() = default;
};

struct B {
    virtual ~B() = default;
};

struct C : A, B{};

void f(const A &a) {
    if(auto p = dynamic_cast<const B*>(&a))
        std::cout << "a is a B" << std::endl;
}

int main() {
    f(C{});

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是为什么如果你从B中删除多态,它仍然有效:

#include <iostream>

struct A{
    virtual ~A() = default;
};

struct B {
};

struct C : A, B{};

void f(const A &a) {
    if(auto p = dynamic_cast<const B*>(&a))
        std::cout << …
Run Code Online (Sandbox Code Playgroud)

c++ dynamic-cast multiple-inheritance vtable vptr

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

std :: variant并在GCC8中移动构造函数Bug

我有这段代码在GCC7.2,clang 7和MSVC中运行得非常好,但在GCC 8.0中没有.显然,它涉及复制构造函数......

#include <iostream>
#include <variant>
#include <memory>
#include <type_traits>

struct EmptyTree{};

struct Node {
    using node = std::unique_ptr<Node>;
    using Tree = std::variant<node, EmptyTree>;

    Node(int v) : value(v){}
    template<typename left, typename right>
    Node(int v, left &&l, right &&r) : value(v), left(std::move(l)), right(std::move(r)){}
    int value;
    Tree left = EmptyTree{};
    Tree right = EmptyTree{};
};

using Tree = Node::Tree;

auto make_node(int v) {
    return std::make_unique<Node>(v);
}

int main() {
    Tree a;
    a = Tree{make_node(5)};
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

用于测试代码的wandbox https://wandbox.org/permlink/Z8yXCen0fqbV3PDD

这是Gcc 8的错误还是我的代码中的错误? …

c++ variant c++17

6
推荐指数
0
解决办法
432
查看次数

SFINAE:删除具有相同原型的函数

我想知道这个代码有什么区别:

#include <type_traits>
#include <iostream>

template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;

template<typename T, is_ref<T> = true>
void foo(T&&) {
    std::cout << "ref" << std::endl;
}

template<typename T, is_not_ref<T> = true>
void foo(T&&) {
    std::cout << "not ref" << std::endl;
}

int main() {
    int a = 0;
    foo(a);
    foo(5);
}
Run Code Online (Sandbox Code Playgroud)

而这个不起作用:

#include <type_traits>
#include <iostream>

template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;

template<typename T, typename …
Run Code Online (Sandbox Code Playgroud)

c++ sfinae template-function c++14 c++17

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

将 int 数组转换为 integer_sequence

我想知道是否有办法将 astd::array转换为索引序列?

constexpr std::array<int, 5> x = {0, 3, 4, 5, 8};

constexpr auto integer_sequence = ...; // something that lead to integer_sequence<int, 0, 3, 4, 5, 8>;
Run Code Online (Sandbox Code Playgroud)

我知道使用一个函数是不可能的,因为它会导致另一种类型。但是,由于可以执行以下操作:

constexpr std::size_t x = 8;
std::integral_constant<int, x> height;
Run Code Online (Sandbox Code Playgroud)

是否有可能以简单的方式做到这一点?

我尝试执行以下操作:

#include <array>
#include <tuple>

template<std::size_t N>
constexpr std::array<int, N> m_iota(int value) {
    std::array<int, N> result{};
    for(auto &v : result)
        v = value++;
    return result;
}

template<int N>
using Int = std::integral_constant<int, N>;

int main() {
    constexpr auto array = …
Run Code Online (Sandbox Code Playgroud)

c++ c++17

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

Vulkan 管道顶部/底部和 ALL_COMMANDS

作为很多“初学者”,我认为使用 TOP_OF_PIPELINE 作为 dst 和 BOTTOM_OF_PIPELINE 作为 src 意味着两者的 ALL_COMMANDS 。

Nicol Bolas在这里写道,“由于管道的顶部/底部对内存屏障没有意义,也许使用它们应该完全无效。因此仅对执行屏障有用。”

据我了解,由于 TOP 和 BOTTOM 不执行任何对内存的访问,因此将屏障放在顶部或底部不能使内存可见^^。

据我了解 Nicol Bolas 的含义以及我刚才所说的内存访问/可见性,当您使用底部或顶部时,必须将 accessMask 设置为 0。

如果我想呈现图像,我可以这样做:

srcStage = COLOR_ATTACHMENT_OUTPUT_BIT
srcAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
oldLayout = ATTACHMENT_OPTIMAL
dstStage = BOTTOM
dstAccess = 0; // Since memory read access will be "issued" by semaphore
newLayout = PRESENT_KHR;
Run Code Online (Sandbox Code Playgroud)

我们在这里使用底部是因为我们不希望内存屏障使当前队列等待,如规范中所述:

当下一个访问将在不同的队列中或由表示引擎完成时,VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT 对于完成内存屏障和布局转换很有用;在这些情况下,同一队列中的后续命令不需要等待,但屏障或转换必须在与批处理信号关联的信号量之前完成。

所以现在,我可以说(我希望...)我了解何时使用每个阶段,但 TOP_OF_PIPE nop...

所以,我的问题是:执行屏障到底是什么(因此没有内存屏障)?它们为什么有用?(因为说一个操作一个接一个地发生很好,但最好说我们可以在第二个操作中使用第一个操作中产生的数据)。什么时候应该在管道底部或顶部放置屏障?

谢谢 !

vulkan

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