- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试模仿 cons-cell
就像函数式编程语言中的列表结构,在 C++ 中使用 constexpr
.我有一个 pair
类型,开始。这是两个不同事物的持有者,但也支持嵌套对。这是代码。
template <typename E1, typename E2>
struct pair {
constexpr pair()
:_car{E1{}}, _cdr{E2{}}
{}
constexpr pair(const E1 &car, const E2 &cdr)
:_car{car}, _cdr{cdr}
{}
constexpr auto car() const{
return _car;
}
constexpr auto cdr() const{
return _cdr;
}
friend std::ostream& operator<<(std::ostream& str,
pair<E1, E2> p){
if(p == pair{})
return str;
str << p.car() << " " << p.cdr();
return str;
}
template <typename Functor>
friend constexpr auto fmap(Functor f,
const pair<E1, E2> p){
if constexpr (std::is_fundamental<E1>::value &&
std::is_fundamental<E2>::value)
return pair{f(p.car()), f(p.cdr())};
else if(std::is_fundamental<E1>::value &&
!std::is_fundamental<E2>::value)
return pair{f(p.car()), fmap(f, p.cdr())};
}
const E1 _car;
const E2 _cdr;
};
template <typename E1, typename E2>
constexpr bool operator==(const pair<E1, E2>& p1, const pair<E1, E2>& p2)
{
return (p1.car() == p2.car()) && (p1.cdr() == p2.cdr());
}
nested_pair
类型。这使我可以更轻松地使用
nested_pair
s .aka 列表。实际列表只是围绕此包装器的 typedef。这是代码。
template <typename Head, typename Tail>
class nested_pair{
public:
constexpr nested_pair():p{}
{}
constexpr nested_pair(Head h, Tail t)
:p{h, t}
{}
constexpr auto prepend(Head h) const{
return nested_pair<Head, decltype(p)>{h, p};
}
constexpr auto head() const {
return p.car();
}
constexpr auto tail() const {
return nested_pair<decltype(p.cdr().car()),
decltype(p.cdr().cdr())>
{p.cdr().car(),
p.cdr().cdr()
};
}
constexpr bool is_empty() const {
return p == pair<decltype(p.car()),
decltype(p.cdr())>
{};
}
template <typename Functor>
friend constexpr auto fmap(Functor f, const nested_pair l) {
const auto res = fmap(f, l.p);
return nested_pair{res.car(), res.cdr()};
}
friend std::ostream& operator<<(std::ostream& str,
nested_pair<Head, Tail> l){
str << l.p;
str << "\n";
return str;
}
private:
const pair<Head, Tail> p;
};
nested_pair
只允许 prepend 因为如果您将列表存储为一对头部和尾部,则 append 需要 O(n) 递归调用。在这里,我将大量工作委托(delegate)给了
pair
和
nested_pair
打包
pair
的构造函数.我相信这些工作正常。我使用以下变量模板将列表定义为嵌套对。
template <typename T>
using list = nested_pair<T, T>;
list
制作
string
类型,如
list<char>
.这应该再次是所有的 constexpr,尽可能多的。我有另一个版本
const char []
构建 constexpr 字符串,但现在我想使用结构递归。这是我失败的尝试。
class lstring{
public:
template <std::size_t N>
constexpr lstring(const char(&cont)[N]) :size{N} {
size_t ind = N - 1;
while(ind >= 0){
content = content.prepend(cont[ind]);
ind--;
}
}
private:
const size_t size;
const list<char> content;
};
char... args
的可变参数模板吗? ?我怎样才能从结构上解开它?我希望能够从像
list<char> s{"hello world"}
这样的字符串文字中初始化它.
最佳答案
你有一个概念问题:
您的 lstring
包含 list<char>
这实际上是一个 nested_pair<char, char>
它又包含一个 pair<char, char>
. 您的字符串始终包含两个 char
s。
字符串类和列表类都需要将它们的长度编码为它们的类型的一部分。 IE。你需要一个 list<char, 5>
获取 5 个列表 char
(因此包含 pair<char, pair<char, pair<char, pair<char, char>>>>
)。否则,您将需要动态内存——这对于编译时常量代码来说是明确的。
现在,进行演示。我希望它能给你一些关于如何实现某些事情的想法。这对我来说也很有趣;) 与您的设计选择相反,我使用了一个特殊的标记值 - nil
- 标记列表的结尾。以下所有代码都在 namespace list
中:
struct nil {
template<typename U>
constexpr auto prepend(U && u) const;
};
nil
(空列表)有一个成员函数模板,可以在前面添加一些东西。它只是声明 - 未定义 - 在这里打破循环依赖。
prepend(mylist, element)
),但我想反射(reflect)您的预期用途(
mylist.prepend(element)
)。
namespace implementation {
template<typename T>
using no_ref_cv = std::remove_cv_t<std::remove_reference_t<T>>;
}
template<typename Car, typename Cdr>
struct cons {
Car car;
Cdr cdr;
template<typename U>
constexpr auto prepend(U && u) const {
using implementation::no_ref_cv;
return cons<no_ref_cv<U>, cons<Car, Cdr>>{std::forward<U>(u), *this};
}
};
prepend
创建一个新的 cons,将新元素作为其第一个元素,并将当前 cons(的拷贝)作为第二个元素。我删除
const
和
volatile
因为否则有点头疼(尝试弄清楚为什么
cons<char, cons<char, cons<const char, cons<char, nil>>>>
不会转换为
cons<char, cons<const char, cons<char, cons<char, nil>>>>
)
nil::prepend
基本上是一样的:
template<typename U>
constexpr auto nil::prepend(U && u) const {
using implementation::no_ref_cv;
return cons<no_ref_cv<U>, nil>{std::forward<U>(u), *this};
}
template<typename Car, typename Cdr>
constexpr auto make_cons(Car && car, Cdr && cdr) {
using implementation::no_ref_cv;
return cons<no_ref_cv<Car>, no_ref_cv<Cdr>>{
std::forward<Car>(car), std::forward<Cdr>(cdr)};
}
How can I unpack this structurally? I want to be able to initialize this from a string literal like
list<char> s{"hello world"}
.
list<char>
不可能(记住——你也需要那里的长度!)。但是
auto s = list::make_list("hello world")
.
CharT (&array)[N]
)并使用该
N
您可以构建具有足够嵌套的类型
cons
保存您的 list :
namespace implementation {
template<typename T, std::size_t N>
struct build_homo_cons_chain {
using type = cons<T, typename build_homo_cons_chain<T, N - 1u>::type>;
};
template<typename T>
struct build_homo_cons_chain<T, 0u> {
using type = nil;
};
}
N == 0
只是一个
nil
(空列表),其他一切都是
cons
带有元素和长度列表
N - 1
.这允许你为你的列表定义正确的类型,你可以使用它来默认初始化它的一个实例,然后循环遍历
car
成员来填补它。像这样的东西:
using list_t = typename implementation::build_homo_cons_chain<char, N>::type;
list_t my_new_list;
// fill my_new_list.car, my_new_list.cdr.car, ... probably with recursion
char
不是问题,但这些都是严格的要求,所以当我们从数组中提供的元素(字符串文字)复制/移动构造列表的元素时,我们会更好:
namespace implementation {
template<std::size_t O, std::size_t C>
struct offset_homo_builder {
template<typename T, std::size_t N>
constexpr auto from( T (&array)[N]) {
return offset_homo_builder<O - 1u, C - 1u>{}.from(array).prepend(array[N - O]);
}
};
template<std::size_t O>
struct offset_homo_builder<O, 0u> {
template<typename T, std::size_t N>
constexpr auto from( T (&array)[N]) {
return nil{};
}
};
}
O
是相对于数组末尾的偏移量,
C
我们仍然需要构建列表的缺点计数。
from
成员函数模板采用长度为
N
的数组并将数组中的元素添加到
N - O
到它递归构建的(较短的)列表。
implementation::offset_homo_builder<3,2>::from("ab")
offset_homo_builder<3,2>::from("ab") --> N = 3, O = 3, C = 2
: cons{'b', nil}.prepend('a') => cons{'a', cons{'b', nil}}
^
|--- offset_homo_builder<2, 1>::from("ab") --> N = 3, O = 2, C = 1
: nil.prepend('b') => cons{'b', nil}
^
|--- offset_homo_builder<1, 0>::from("ab") --> N = 3, O = 1, C = 0 (!specialisation!)
: nil
C
计数很重要,忽略
'\0'
在字符串文字的末尾。所以现在你可以创建一个包含数组所有元素的列表:
template<typename T, std::size_t N>
constexpr auto make_homogenous(T (&array)[N]) {
return implementation::offset_homo_builder<N, N>{}.from(array);
}
template<std::size_t N, typename CharT, typename = typename std::char_traits<CharT>::char_type>
constexpr auto make_string(CharT (& array)[N]) {
static_assert(N > 0, "assuming zero terminated char array!");
return implementation::offset_homo_builder<N, N - 1>{}.from(array);
}
nil
:
template<typename F, typename Car, typename Cdr>
constexpr auto fmap(F functor, cons<Car,Cdr> const & cell) {
return make_cons(functor(cell.car), fmap(functor, cell.cdr));
}
template<typename F>
constexpr auto fmap(F functor, nil const &) {
return nil{};
}
foldl
,
foldr
和 friend 可以类似地实现。您的
operator<<
可以使用
foldl
实现.
namespace list
.
constexpr
:
constexpr char inc(char c) {
return c + 1;
}
static_assert(fmap(inc, list::make_string("ab").prepend('x')).car == 'y', "");
fmap
而不是
list::fmap
.适用于通用代码。
关于c++ - List<Char> 在 C++ 中键入 constexpr 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49741416/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!