特别是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) 我使用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.
如果我的页面大小设置正确,我可以从当前和以前加载的页面提供所有这些请求.
如果CanSelectMultipleItems是True并且用户使用SHIFT按钮或鼠标拖动选择多个项目,则DataGrid枚举从列表开头到选择结尾的所有行.IEnumerable无论IList是否实现,此枚举都通过接口发生.
如果所选行不可见且当前可见区域与所选行"远",则有时DataGrid会开始请求从所选行到可见区域末尾的所有项目.包括其间甚至不可见的所有行.我无法弄清楚这种行为的确切模式.也许我的实施就是这个原因.
我的问题
我想知道,为什么DataGrid不可见行的请求,因为这些行将在可见时再次请求?
为什么有必要要求每一行两到三次?
任何人都可以告诉我如何使DataGrid不使用IEnumerable,除了关闭多个项目选择?
可以在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'.
除了"因为语法这么说"之外还有其他原因吗?我该如何解决它?
我正在使用VC++ 03,其中Foo:
...所以我宁愿避免复制或重复它的类型.
注意:虽然我的实际问题是C++ 03,但我(学术上)对C++ 11中的答案很感兴趣.
考虑以下代码:
#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) 我偶然发现了std::alignment_of类型特征,以及即将成为朋友的类型特征std::alignment_of_v.它们似乎专门设计为等同于普通调用alignof,并且未来添加_v帮助程序表明它不仅仅是遗留位.
有什么用的std::alignment_of(_v),当我们有alignof?
我有以下课程:
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::map在maps得到与它匹配的钥匙叫什么名字?
例如,如果我有
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) 实际上,分段错误发生在我试图编译的另一个程序中,这是因为这种行为.
我的问题是:
这是一个错误还是我的错?
可以任何方式重现(即使该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)
并运行: …
我想写一个概念 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 的事实。我错过了什么?
虽然我偶然发现了这个问题的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
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++ ×9
c++11 ×2
c++17 ×2
compiler-bug ×2
alignof ×1
c++-concepts ×1
c++03 ×1
c++14 ×1
clang ×1
constexpr ×1
datagrid ×1
if-statement ×1
native ×1
parameters ×1
wpf ×1