标签: library-design

.NET中的readonly/const在哪里?

在C++中,你会看到void func(const T& t)无处不在.但是,我在.NET中没有看到类似的东西.为什么?

我注意到使用struct的参数很多.但是我看不到readonly/const的函数.事实上,现在我尝试了它,我不能使用这些关键字来制作一个承诺不修改传入的列表的函数.有没有办法让调用者承诺这个函数永远不会修改列表的内容?有没有办法说调用代码并说这个列表永远不应该被修改?(我知道我可以克隆列表或查看文档,但我喜欢编译错误)

.net language-design library-design

30
推荐指数
3
解决办法
584
查看次数

库设计:允许用户在"仅标题"和动态链接之间做出决定?

我创建了几个目前只有标头的 C++库.我的类的接口和实现都写在同一个.hpp文件中.

我最近开始认为这种设计不是很好:

  1. 如果用户想要编译库并动态链接它,他/她就不能.
  2. 更改单行代码需要完全重新编译依赖于库的现有项目.

我真的很喜欢只有头文件库的方面:所有函​​数都可以内联,并且它们非常容易包含在你的项目中 - 不需要编译/链接任何东西,只需要一个简单的#include指令.

是否有可能充分利用两个世界?我的意思是 - 允许用户选择他/她想要如何使用库.它还可以加快开发速度,因为我以"动态链接模式"处理库以避免荒谬的编译时间,并以"仅标题模式"发布我的成品以最大化性能.

第一个逻辑步骤是将接口和实现划分为.hpp.inl文件.

不过,我不确定如何前进.我已经看到很多库将LIBRARY_API宏添加到它们的函数/类声明中 - 可能需要类似的东西来允许用户选择?


我的所有库函数都以inline关键字为前缀,以避免"多个定义......"错误.我假设关键字将被文件中的LIBRARY_INLINE宏替换.inl?宏将解析inline为"仅标题模式",而不是"动态链接模式".

c++ library-design libraries header-only c++11

29
推荐指数
2
解决办法
2687
查看次数

为什么.Net框架没有优先级队列类?

Stack Overflow上有一些线程涉及在.Net和C#中实现优先级队列.

我的问题是一个更基本的问题:为什么在.Net框架中没有开箱即用的优先级队列?甚至C++标准库也有一个.

.net priority-queue standard-library library-design data-structures

21
推荐指数
2
解决办法
3111
查看次数

Function.const的目的是什么?

它在ScalaDoc中但没有太多文档.它似乎总是返回第一个参数.

Function.const(1)(2)例如返回1.

它为什么存在,为什么有用?

parameters scala const function library-design

17
推荐指数
2
解决办法
3663
查看次数

为什么std :: fstream设置EOF位的方式呢?

我最近遇到了使用fstream :: eof()引起的问题.我从这里读到以下内容:

如果已到达关联输入文件的末尾,则函数eof()将返回true,否则返回false.

并且(错误地)假设这意味着如果我使用fstream :: read()并读取文件末尾,函数eof()会告诉我.所以我做了这样的事情(非常概括):

for(int i = 0; i < max && !file.eof(); i++)
{
     file.read(mything, sizeof(mything));
}
Run Code Online (Sandbox Code Playgroud)

出现这个问题的原因是上面链接的页面稍后解释了(由于误导性的第一段,我最初没有阅读):

相反,如果在最后一个令牌之后恰好有任何空格,则流不会进入EOF状态,但尝试读取另一个令牌仍然会失败.因此,EOF标志不能用作用于在EOF之前读取所有流内容的循环中的测试.相反,应该在尝试阅读后检查失败条件.

所以我改变了,现在我的循环检查file.fail()而不是file.eof(),我理解如何工作eof().我的问题是,为什么这样做?有没有这种情况需要?在我看来,一旦你通过EOF,你已经通过了EOF而eof()应该返回true.

更新 感谢您的回复,我想我已经得到了.我正在执行的唯一操作是read(),我立即检查fail(),所以我觉得我没事.现在,我的问题是,我使用eof()?

c++ iostream library-design

15
推荐指数
1
解决办法
7262
查看次数

std :: multiplies和std :: divides是否有任何理由成为第三人称?

今天,我们发现,对于乘除,仿函数被称为std::multipliesstd::divides,而不是,例如, std::multiplystd::divide分别.

至少可以说这是令人惊讶的,考虑到std::plus并且std::minus没有以相同的方式制定.

差异有特殊原因吗?

c++ library-design

15
推荐指数
1
解决办法
863
查看次数

使用C和C++接口编写库,以哪种方式包装?

在准备一个库(让我们称之为libfoo)时,我发现自己面临以下困境:我是否将其编写为带有C包装器的C++库:

namespace Foo {
  class Bar {
    ...
  };
}

/* Separate C header. #ifdef __cplusplus omitted for brevity. */
extern "C" {
  typedef void *FooBar;
  FooBar* foo_bar_new() { return new Foo::Bar; }
  void foo_bar_delete(FooBar *bar) { delete bar; }
}
Run Code Online (Sandbox Code Playgroud)

或者将它编写为带有C++包装器的C库更好:

/* foo/bar.h. Again, #ifdef __cplusplus stuff omitted. */

typedef struct {
  /* ... */
} FooBar;

void foo_bar_init(FooBar *self) { /* ... */ }
void foo_bar_deinit(FooBar *self) { /* ... */ }

/* foo/bar.hpp */

namespace Foo { …
Run Code Online (Sandbox Code Playgroud)

c c++ library-design

14
推荐指数
3
解决办法
6803
查看次数

为什么std :: count(_if)返回iterator :: difference_type而不是size_t?

可能重复:
为什么C++标准算法"count"会返回ptrdiff_t而不是size_t?

标准C++中有算法std::count/ std::count_if.

template<class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, const T& value);

template<class InputIterator, class Predicate>
typename iterator_traits<InputIterator>::difference_type
count_if(InputIterator first, InputIterator last, Predicate pred);
Run Code Online (Sandbox Code Playgroud)

效果:返回以下相应条件所适用的[first,last]范围内的迭代器数量:*i == value,pred(*i)!= false.

difference_typeiterator's difference_type,可以是负数,但count只能返回值> = 0.为什么difference_type而不是size_t例如?

c++ library-design stl-algorithm c++11

14
推荐指数
1
解决办法
2073
查看次数

为什么泛型IList <>不继承非泛型IList

IList<T>不继承IList那里IEnumerable<out T>继承IEnumerable.

如果out修正是唯一的原因,那么为什么大多数的实施IList<T>(例如Collection<T>,List<T>)实现IList接口.

所以任何人都可以说好,如果那些陈述对于所有的实现都是真的,IList<T>那么IList在必要时直接将其强制转换.但问题是虽然IList<T>没有继承IList所以不能保证每个IList<T>对象都是IList.

此外,使用IList<object>显然不是解决方案,因为没有out修饰符泛型不能分配给较少的继承类; 并且创建List的新实例在这里不是解决方案,因为有人可能想要实际引用IList<T>作为IList指针; 并且使用List<T>insteed IList<T>实际上是一种糟糕的编程习惯,并不能用于所有目的.

如果.NET希望提供灵活性,每个实现IList<T>都不应该有非泛型实现的合同(即IList)那么为什么他们没有保留另一个实现泛型和非泛型版本的接口,并没有暗示所有具体的想要签订通用和非遗传项目的类应通过该接口签订合同.

发生铸造同样的问题ICollection<T>,以ICollectionIDictionary<TKey, TValue>IDictionary.

.net c# generics library-design

14
推荐指数
1
解决办法
2978
查看次数

为什么TStringList有BeginUpdate和EndUpdate?

我知道在TLI控件(如TListBox)上使用BeginUpdate和EndUpdate会加快使用Items填充控件的过程,因为它会阻止控件重新绘制,直到调用EndUpdate.

例:

procedure TForm1.AddItems;
var
  i: Integer;
begin
  Screen.Cursor := crHourGlass;
  try
    for i := 0 to 5000 do
    begin
      ListBox1.Items.Add('Item' + IntToStr(i));
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

上面会有延迟,因为允许重新绘制列表框,但是可以通过防止重新绘制来缩短延迟:

procedure TForm1.AddItems;
var
  i: Integer;
begin
  Screen.Cursor := crHourGlass;
  try
    ListBox1.Items.BeginUpdate;
    try
      for i := 0 to 5000 do
      begin
        ListBox1.Items.Add('Item' + IntToStr(i));
      end;
    finally
      ListBox1.Items.EndUpdate;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

现在我使用TStringList测试了这个:

procedure TForm1.AddItems;
var
  SL: TStringList;
  i: Integer;
begin
  SL := TStringList.Create;
  try
    Screen.Cursor := crHourGlass; …
Run Code Online (Sandbox Code Playgroud)

delphi library-design

13
推荐指数
2
解决办法
3548
查看次数