我目前正在尝试围绕类型类和实例,我还不太明白它们的意义.到目前为止,我对此事有两个问题:
1)当函数使用该类型类中的某些函数时,为什么必须在函数签名中使用类型类.例:
f :: (Eq a) => a -> a -> Bool
f a b = a == b
Run Code Online (Sandbox Code Playgroud)
为什么要(Eq a)签名.如果==没有定义a那么为什么不在遇到时抛出错误a == b?必须提前声明类型类有什么意义?
2)类型类和函数重载如何相关?
这样做是不可能的:
data A = A
data B = B
f :: A -> A
f a = a
f :: B -> B
f b = b
Run Code Online (Sandbox Code Playgroud)
但是可以这样做:
data A = A
data B = B
class F a where
f :: a -> a
instance F A …Run Code Online (Sandbox Code Playgroud) 我试图让这个片段编译
#include <vector>
#include <numeric>
#include <execution>
double result = std::reduce(std::execution::par, v.begin(), v.end());
Run Code Online (Sandbox Code Playgroud)
我试过这些编译器:
Apple LLVM version 8.1.0 (clang-802.0.42)
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Run Code Online (Sandbox Code Playgroud)
这三个人都给了我 'execution' file not found
分别 error: no member named 'reduce' in namespace 'std'
auto result = std::reduce(v.begin(), v.end());
对于这个片段
#include<numeric>
#include<vector>
int main(int argc, char *argv[])
{
std::vector<double> v(10, 1);
auto result = std::reduce(v.begin(), v.end());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想我的编译器太旧了?但是在cppreference上它没有说明哪个编译器版本最低,而且我没有在repo中看到任何更新版本的clang或gcc.
是否可以在可变参数模板参数中混合类型和非类型?如果我将一个std::arrayfor例作为参数传递给这个类T,我还需要传递一个数组类型和一个长度,但是我在下面尝试它的方式在遇到一个值时会导致错误,因为它只需要类型为Types:
template <
template<class, std::size_t> class T,
class ... Types>
class C {
T<Types...> storage;
};
int main(){
C<std::array, int, 3> c;
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
error: template argument for template type parameter must be a
type
Container<std::array, int, 3> c;
^
Run Code Online (Sandbox Code Playgroud)
有没有办法在可变参数上下文中传递类型和值?
我需要构建一个n类型的元组.这n种类型是n种其他类型的值类型.请考虑以下代码段:
#include <boost/hana.hpp>
namespace hana = boost::hana;
template<class... Types>
class CartesianProduct
{
public:
CartesianProduct(Types... args) : sets(args...) {}
hana::tuple<Types...> sets;
hana::tuple<Types...::value_type> combination; // does not work obviously... but wo can this be done?
};
Run Code Online (Sandbox Code Playgroud)
应用程序的目的是这样的:我向这个类传递一个可能不同类型的容器的参数包.该类将这些容器放入元组中sets.该类还有一个字段combination,它是容器传递给类的元素数量的元组.但元素的类型是不同容器的值类型.
然后,该类旨在懒惰地构建传递给它的容器的笛卡尔积,并将当前组合存储在其中combination.但是,我怎样才能以可变方式实际获取容器的值类型?
我收到这个错误
comparison between pointer and integer ('int' and 'const char *')
Run Code Online (Sandbox Code Playgroud)
对于以下代码
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
std::string s("test string");
for(auto i = s.begin(); i != s.end(); ++i)
{
cout << ((*i) != "s") << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
为什么解引用字符串迭代器会产生一个int而不是std::string?
我对CRTP的编译方式感到困惑.如果我们有这样的事情:
template<class T>
class Base
{
};
class Derived : public Base<Derived>
{
};
Run Code Online (Sandbox Code Playgroud)
为什么在编译期间没有类似的事情发生?
(X[Y]表示X继承自Y)
在声明Derived实例时
Derived d;
d 正在扩展为模板和继承的无限复发
d[Base<Derived[Base<Derived[Base<Derived[Base<Derived[...]>]>]>]>]
为什么这不会发生?关于CRTP的所有教程只解释了你可以用它做什么,而不是在幕后发生的事情(至少含糊不清).
在C++ 11下,可以在声明时直接初始化类成员.但是也可以在构造函数的初始化列表中再次初始化它们......为什么?
#include <iostream>
struct MyStr
{
MyStr()
:j(0)
{
std::cout << "j is " << j << std::endl; // prints "j is 0"
}
const int j = 1;
};
int main()
{
const int i = 0;
MyStr mstr;
}
Run Code Online (Sandbox Code Playgroud)
因为做这样的事情是一个错误,可以理解:
MyStr()
:j(0),
j(1)
{
}
Run Code Online (Sandbox Code Playgroud)
第一个例子有什么不同,数据成员在声明时初始化,然后再在构造函数的初始化列表中初始化?
我想使用基类的模板函数,如下所示:
struct A {
template <class T> static auto f() { \*code*\ }
};
template <class A_type> struct B : public A_type {
using A_type::f;
void g() { auto n = f<int>(); }
};
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译。
error: expected '(' for function-style cast or type
construction
void g() { auto n = f<int>(); }
~~~^
error: expected expression
void g() { auto n = f<int>(); }
Run Code Online (Sandbox Code Playgroud)
但是直接引用基类而不是模板确实有效:
struct A {
template <class T> static auto f() { \*code*\ }
};
template <class …Run Code Online (Sandbox Code Playgroud) 我的代码中具有以下功能,用于检查数字(在日志空间中)是否具有允许的值:
template<class T>
static void check_if_normal(T t)
{
T additive_neutral_element = make_additive_neutral_element<T>();
// probability is allowed to be 0 in logspace
// probability also is allowed to be -inf in logspace
if (!std::isnormal(t) && t != 0 && t != additive_neutral_element)
throw std::underflow_error(
"Probability of " + std::to_string(t) +
" is abnormal --- possible cause underflow.");
}
Run Code Online (Sandbox Code Playgroud)
在使用此函数的上下文中,我排他性地使用了长双精度。当我在不使用valgrind的情况下运行程序时,一切正常,但是当我在使用valgrind的程序运行时,该函数实际上会引发异常。我怀疑valgrind所做的事情会改变长双打的格式,或者类似的行为。我找到了这个:
Valgrind在相对于IEEE754的x86 / AMD64浮点实现中具有以下限制。
精度:不支持80位算术。在内部,Valgrind用64位表示所有此类“长双精度”数字,因此结果可能有所不同。这是否很关键还有待观察。请注意,x86 / amd64 fldt / fstpt指令(读/写80位数字)已使用到64位的转换进行了正确模拟,因此,如果有人要查看,则80位数字的内存图像看起来正确。
从许多FP回归测试中观察到的印象是,准确性差异并不明显。一般而言,如果程序依赖于80位精度,则可能很难将其移植到仅支持64位FP精度的非x86 / amd64平台。即使在x86 / amd64上,该程序也可能会获得不同的结果,具体取决于它是编译为使用SSE2指令(仅64位)还是x87指令(80位)。最终结果是使FP程序的行为就像在具有64位IEEE浮点数的计算机(例如PowerPC)上运行时一样。在amd64上,FPD算术运算默认情况下是在SSE2上完成的,因此从FP角度来看,amd64看起来更像PowerPC,而不是x86,并且与x86相比,明显的精度差异要少得多。
舍入:Valgrind确实对以下转换遵循4种IEEE规定的舍入模式(至最接近,至+无限,至-无限,至零):浮于整数,整数可能浮于精度的情况,以及浮动到浮动的舍入。对于所有其他FP操作,仅支持IEEE默认模式(四舍五入到最接近)。
FP代码中的数字异常:IEEE754定义了五种可能发生的数字异常:无效操作(负数的平方等),被零除,溢出,下溢,不精确(精度损失)。
对于每个异常,IEEE754定义了两个动作过程:(1)可以调用用户定义的异常处理程序,或者(2)定义一个默认动作,该动作可以“修正”并允许计算继续进行而无需引发异常。
当前,Valgrind仅支持默认的修正操作。同样,对于异常支持的重要性的反馈将不胜感激。
当Valgrind检测到程序试图超出这些限制中的任何一个(设置异常处理程序,舍入模式或精度控制)时,它可以打印一条消息,提供对该事件发生的位置的追溯,并继续执行。此行为曾经是默认行为,但是消息很烦人,因此默认情况下现在禁用显示消息。使用--show-emwarns = yes可以查看它们。
以上限制精确地定义了IEEE754的“默认”行为:所有异常的默认修正,最近舍入操作和64位精度。 …
有没有办法从跟踪中隐藏单个谓词?在这样的规则中:
p(<Stuff>) :-
q(),
p(<ModifiedStuff>);
s(),
p(<ModifiedStuff>);
p(<ModifiedStuff>).
Run Code Online (Sandbox Code Playgroud)
例如,我想隐藏q()和隐藏s()踪迹,因为我仅对的调用感兴趣p()。
q()并且s()可能会调用许多其他谓词,这完全阻塞了跟踪,并使其很难在其中找到相关的调用。
现在,我尝试从命令行而不是从解释器内部执行,并将跟踪管道传递给grep以对包含p...的行进行grepping ,但令我失望的是,从命令行运行时,它仍然打开了一个prolog shell,因此,对输出进行管道传输根本不起作用。只有print将实际发送到运行Prolog进程的Shell。
?- trace(shift_reduce, all).
% shift_reduce/2: [call,redo,exit,fail]
true.
[debug] ?- shift_reduce([?,x,x], T).
T Call: (8) shift_reduce([?, x, x], _7344)
T Exit: (8) shift_reduce([?, x, x], [e, [?], [v, [x]], [e, [v, [...]]]])
T = [e, [?], [v, [x]], [e, [v, [x]]]] ;
T Exit: (8) shift_reduce([?, x, x], [e, [?], [v, [x]], [e, …Run Code Online (Sandbox Code Playgroud) c++ ×8
inheritance ×2
boost-hana ×1
c++11 ×1
c++17 ×1
crtp ×1
dereference ×1
haskell ×1
header ×1
iterator ×1
long-double ×1
numeric ×1
overloading ×1
prolog ×1
string ×1
swi-prolog ×1
templates ×1
trace ×1
tuples ×1
typeclass ×1
valgrind ×1