小编Que*_*tin的帖子

Clang和二进制折叠表达式 - 空参数包的诅咒

特别是Clang 3.6.0,目前由Coliru主持.

所有这些片段都来自:

int main() {
    foo();
    std::cout << "\n----\n";
    foo(1, 2, 3);
}
Run Code Online (Sandbox Code Playgroud)

以下代码:

template <class... Args>
void foo(Args... args) {
    std::cout << ... << args;
}
Run Code Online (Sandbox Code Playgroud)

触发以下编译错误:

main.cpp:7:17: error: expected ';' after expression
    std::cout << ... << args;
                ^
                ;
main.cpp:7:15: error: expected expression
    std::cout << ... << args;
              ^
Run Code Online (Sandbox Code Playgroud)

所以我试着在表达式周围添加括号:

(std::cout << ... << args);
Run Code Online (Sandbox Code Playgroud)

它有效,但会触发警告:

main.cpp:7:6: warning: expression result unused [-Wunused-value]
    (std::cout << ... << args);
     ^~~~~~~~~
main.cpp:11:5: note: in instantiation of function template specialization 'foo<>' …
Run Code Online (Sandbox Code Playgroud)

c++ clang compiler-bug fold-expression c++17

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

DataGrid行请求模式与数据虚拟化

我使用CodePlex的一些想法和Bea Stollnitz的博客以及Vincent Da Ven Berhge的论文(同一链接)实现了数据虚拟化解决方案.但是我需要一种不同的方法,所以我决定编写自己的解决方案.

DataGrid用这个解决方案来显示大约一百万行.我也在使用UI虚拟化.我的解决方案是可行的,但我在某些情况下遇到了一些奇怪的行为,这些行为是关于如何DataGrid从源头请求数据的.

关于解决方案

我最终编写了一份列表来完成所有繁重的工作.它是一个名为VirtualList<T>.It 的泛型类,它实现了ICollectionViewFactory接口,因此集合视图创建机制可以创建一个VirtualListCollectionView<T>实例来包装它.这个类继承自ListCollectionView.我没有按照建议编写我自己的ICollectionView实现.继承似乎也很好.

VirtualList<T>分裂整个数据到页.它获取总项数,每次DataGrid通过列表索引器对行进行请求时,它会加载相应的页面或从缓存中返回.页面在内部回收,并DispatcherTimer在空闲时间处理未使用的页面.

数据请求模式

  • 我学到的第一件事就是VirtualList<T>实现IList(非泛型).否则,ItemsControl它将把它视为一个IEnumerable并查询/枚举所有行.这是合乎逻辑的,因为DataGrid它不是类型安全的,所以它不能使用IList<T>接口.

  • 带有0索引的行经常被问到DataGrid.它似乎用于视觉项目测量(根据调用堆栈).所以,我只是缓存这一个.

  • 内部的缓存机制DataGrid使用可预测的模式来查询它显示的行.首先它要求从上到下的可见行(每行两次),然后它在可见区域(包括第一个可见行)之前查询几行(取决于可见区域的大小)从下到上依次订购.之后,它在从上到下的可见行(包括最后一个可见行)之后请求相同数量的行.

    如果可见行索引是4,5,6.数据请求将是:4,4,5,5,6,6,4,3,2,1,6,7,8,9.

    如果我的页面大小设置正确,我可以从当前和以前加载的页面提供所有这些请求.

  • 如果CanSelectMultipleItemsTrue并且用户使用SHIFT按钮或鼠标拖动选择多个项目,则DataGrid枚举从列表开头到选择结尾的所有行.IEnumerable无论IList是否实现,此枚举都通过接口发生.

  • 如果所选行不可见且当前可见区域与所选行"远",则有时DataGrid会开始请求从所选行到可见区域末尾的所有项目.包括其间甚至不可见的所有行.我无法弄清楚这种行为的确切模式.也许我的实施就是这个原因.

我的问题

  • 我想知道,为什么DataGrid不可见行的请求,因为这些行将在可见时再次请求?

  • 为什么有必要要求每一行两到三次?

  • 任何人都可以告诉我如何使DataGrid不使用IEnumerable,除了关闭多个项目选择?

wpf datagrid data-virtualization

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

直接初始化条件内的对象

可以在if语句的条件内定义和复制初始化变量:

if(int i = 17) { ... }
Run Code Online (Sandbox Code Playgroud)

这也适用于用户定义的类型,因为它们会重载operator bool:

if(Foo f = 42)      { ... }
if(Foo f = Foo(43)) { ... }
Run Code Online (Sandbox Code Playgroud)

为什么我不能使用直接初始化,如下所示?

if(Foo f(51)) { ... }
Run Code Online (Sandbox Code Playgroud)

GCC发布error: expected primary-expression before 'f'.

住在Coliru

除了"因为语法这么说"之外还有其他原因吗?我该如何解决它?

我正在使用VC++ 03,其中Foo:

  • 是一个RAII敏感的对象,我注意不要定义一个复制构造函数
  • 是一个从用户那里获取参数的模板
  • 有一个双参数构造函数

...所以我宁愿避免复制或重复它的类型.

注意:虽然我的实际问题是C++ 03,但我(学术上)对C++ 11中的答案很感兴趣.

c++ if-statement initialization c++03

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

带有大括号的char数组的非静态成员初始化在gcc中给出错误,而不是在clang中

考虑以下代码:

#include <iostream>

class A
{
    char name[40] = { "Blank" }; // note the braces here
public:
    const char *getName() { return name; }
};

int main()
{
    A a;

    std::cout << a.getName() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

它在gcc(最新版本5.2.0)中出错:

prog.cpp:5:28: error: invalid conversion from 'const char*' to 'char' [-fpermissive]
  char name[40] = { "Blank" };
                            ^
Run Code Online (Sandbox Code Playgroud)

但情况并非如此clang,它可以完美地编译它-std=c++11 -pedantic -Wall.

在这里为非静态初始化程序添加大括号是否真的不正确?

AFAIR是否存在牙箍并不重要.例如,数组的定义,例如:

char text[] = "some text";
Run Code Online (Sandbox Code Playgroud)

相当于:

char text[] = { "some text" …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++11

11
推荐指数
2
解决办法
624
查看次数

`std :: alignment_of`与`alignof`

我偶然发现了std::alignment_of类型特征,以及即将成为朋友的类型特征std::alignment_of_v.它们似乎专门设计为等同于普通调用alignof,并且未来添加_v帮助程序表明它不仅仅是遗留位.

有什么用的std::alignment_of(_v),当我们有alignof

c++ memory-alignment alignof c++17

11
推荐指数
2
解决办法
1104
查看次数

压缩`std :: tuple`和可变参数

我有以下课程:

template<typename... Tkeys>
class C
{
public:
    std::tuple<std::unordered_map<Tkeys, int>... > maps;

    // Not real function:
    void foo(Tkeys... keys) {
        maps[keys] = 1;
    }
};
Run Code Online (Sandbox Code Playgroud)

我将如何实现foo这样它分配给每个std::mapmaps得到与它匹配的钥匙叫什么名字?

例如,如果我有

C<int, int, float, std::string> c;
Run Code Online (Sandbox Code Playgroud)

我打来电话

c.foo(1, 2, 3.3, "qwerty")
Run Code Online (Sandbox Code Playgroud)

c.maps应该相当于

m1 = std::map<int, int>()
m1[1] = 1;
m2 = std::map<int, int>()
m2[2] = 1;
m3 = std::map<float, int>()
m3[3.3] = 1;
m4 = std::map<std::string, int>()
m4["qwerty"] = 1;
c.maps = std::make_tuple(m1, m2, m3, m4);
Run Code Online (Sandbox Code Playgroud)

c++ variadic-templates c++11 c++14

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

委托构造函数在使用类字段进行参数时会出现分段错误

实际上,分段错误发生在我试图编译的另一个程序中,这是因为这种行为.

我的问题是:

这是一个错误还是我的错?

可以任何方式重现(即使该something字段是私有的或受保护的),这是我的例子:

main.cc:

#include <iostream>
class Test {
    public:
        const char* something = "SOMETHING HERE!!!";
        Test(const int& number) : Test(something, number) { }
        // XXX: changed `something` to `_something` to make it different
        Test(const char* _something, const int& number) {
            std::cout << _something << std::endl;
            std::cout << number << std::endl; }
        ~Test() { }
};

int main(int argc, char* argv[]) {
    Test te1(345);
    Test te2("asdasdad", 34523);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

以下是编译时发生的情况:

g++ main.cc -Os -o main
Run Code Online (Sandbox Code Playgroud)

并运行: …

c++ native delegating-constructor raspberry-pi3

11
推荐指数
2
解决办法
666
查看次数

概念 TS 检查忽略私有访问修饰符

我想写一个概念 Indexable 意思是一个序列要么有开始/结束,返回 RandomAccessIterator,要么 operator[] 被定义并返回一个非 void 类型的值。

我将Stroustrup 文章中的想法用于 Sequence 概念,并对其进行了扩充:

template <class T>
concept bool Indexable = Sequence<T> || requires(T t, size_t n) {
    { t[n] } -> NotVoid;
};
Run Code Online (Sandbox Code Playgroud)

它适用于大多数情况,但在以下情况下失败:

struct Bad {
    std::vector<int> nums;

private:
    int& operator[](size_t ind) {
        return nums[ind];
    }
};

static_assert(!Indexable<Bad>, "fail");
Run Code Online (Sandbox Code Playgroud)

出于某种原因,我的概念忽略了 operator[] 被定义为私有并返回 true 的事实。我错过了什么?

c++ c++-concepts

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

在另一个函数内转发声明`constexpr`函数 - 编译错误?

虽然我偶然发现了这个问题的MCVE ,但我发现编译器之间存在以下差异:

请考虑以下代码:

// constexpr int f(); // 1

constexpr int g() {
    constexpr int f(); // 2
    return f();
}

constexpr int f() {
    return 42;
}

int main() {
    constexpr int i = g();
    return i;
}
Run Code Online (Sandbox Code Playgroud)

此代码在Clang 3.8.0上编译,但在GCC 6.1.0上失败:

error: 'constexpr int f()' used before its definition
Run Code Online (Sandbox Code Playgroud)

在两个编译器上评论// 2和取消注释// 1.

有趣的是,移动f的定义代替了// 1编译,但在// 2以下情况下触发了警告:

warning: inline function 'constexpr int f()' used but never defined
Run Code Online (Sandbox Code Playgroud)

哪个编译器是对的?

c++ language-lawyer compiler-bug function-declaration constexpr

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

在自己的默认值中使用参数名称 - 是否合法?

enum class E {
    One,
    Two
};

void foo(E value = decltype(value)::One) {
}
Run Code Online (Sandbox Code Playgroud)

它可以用Clang(3.9)编译,但不能用GCC 6.1编译:value was not declared in this scope.

什么编译器是对的?

c++ parameters language-lawyer default-parameters

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