我需要能够动态加载Haskell模块,并在动态加载模块的上下文中计算表达式.
提示做到了; 问题是,它至少在Windows上不适用于GHCi.
cygwin-bash> ghci HintTest.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Ok, modules loaded: Main.
Prelude Main>
Prelude Main> main
[... lots of "Loading package" messages snipped]
GHCi runtime linker: fatal error: I found a duplicate definition for symbol
_debugLn
whilst processing object file
C:\PROGRAM FILES (X86)\HASKELL PLATFORM\2013.2.0.0\lib\ghc-prim-0.3.0.0\HSghc-prim-0.3.0.0.o
This could be caused by:
* Loading two …Run Code Online (Sandbox Code Playgroud) 一个可以extern "C"函数接受或返回C++ -特定的数据类型,如参考文献,指针到成员或非POD类(由值)?我在C++标准中找不到禁止此内容的任何内容.从逻辑上讲,我希望标准可以说一些,因为C ABI不一定适合传递这类类型.
我想要使用C链接的原因与C编译器无关.该函数仅从C++代码调用.我只想从动态库中导出未编码的函数名.
一个愚蠢的代码示例:
class Foo {
public:
virtual void doit() = 0;
};
class Bar : public Foo {
public:
void doit() { std::cout << "Bar" << std::endl; }
};
extern "C" Foo& getFoo() { static Bar bar; return bar; }
extern "C" Bar getBar() { return Bar(); }
Run Code Online (Sandbox Code Playgroud)
这在Linux上用GCC编译,并按预期工作.应该是标准吗?
问题是对这个问题的评论中的讨论的后续行动.
更新我用Comeau编译器对此进行了测试,它没有抱怨.
这个编译和工作应该(非嵌套模板):
#include <iostream>
template<typename T> class Z;
template <typename T>
std::ostream& operator<< (std::ostream& os, const Z<T>&) {
return (os << "Z");
}
template<typename T> class Z {
friend std::ostream& operator<< <> (std::ostream& os, const Z&);
};
int main () {
Z<int> z;
std::cout << z << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这个不编译(gcc 4.4和gcc 4.6,在03和0x模式下):
#include <iostream>
template<typename T> class Z;
template<typename T>
std::ostream& operator<< (std::ostream& os, const typename Z<T>::ZZ&) {
return (os << "ZZ!");
}
template <typename T> class Z {
public:
class …Run Code Online (Sandbox Code Playgroud) 是否可以定义用户定义的字符串文字转换运算符,使其结果的类型取决于其字符串输入的值?
用户定义的整数和浮点文字很容易,因为它们允许文字运算符模板,文字的实际字符作为模板参数传递给它.例:
template <char... s> struct silly { using type = int; };
template <char... s> struct silly<'1', s...> { using type = double; };
template <char... s>
typename silly<s...>::type operator"" _silly() { return 0; }
static_assert(std::is_same<int, decltype(4321_silly)>::value, "no luck");
static_assert(std::is_same<double, decltype(1234_silly)>::value, "no luck");
Run Code Online (Sandbox Code Playgroud)
用户定义的字符串文字似乎不存在这样的事情.
是否有另一种方法可以做到这一点,无论是在现行标准中,还是计划/讨论过的未来版本?
考虑这个功能模板:
template <class... T>
void foo (std::tuple<T, char, double> ... x);
Run Code Online (Sandbox Code Playgroud)
此调用有效:
using K = std::tuple<int, char, double>;
foo ( K{1,'2',3.0}, K{4,'5',6.0}, K{7,'8',9.0} );
Run Code Online (Sandbox Code Playgroud)
这个没有:
foo ( {1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0} );
Run Code Online (Sandbox Code Playgroud)
(gcc和clang都抱怨过多论据foo)
为什么第二次调用有问题?我可以重写声明,foo以便第二次通话也被接受吗?
模板参数T仅用于实现可变参数.实际类型是已知和固定的,只有参数的数量不同.在现实生活中,类型不同int, char, double,这只是一个例子.
我不能使用C++ 17.更喜欢C++ 11兼容的解决方案.
如何编写std::array串联函数?
template <typename T, std::size_t sza, std::size_t szb>
std::array<T, sza+szb> concat (const std::array<T, sza>& aa,
const std::array<T, szb>& ab)
{
std::array<T, sza+szb> result;
std::copy(std::begin(aa), std::end(aa), std::begin(result));
std::copy(std::begin(ab), std::end(ab), std::begin(result) + sza);
return result;
}
Run Code Online (Sandbox Code Playgroud)
T当不可默认构造时,这当然不起作用。如何解决这个问题?
我试图理解类型家庭没有太大的成功.这是一个最小的例子:
{-# LANGUAGE TypeFamilies #-}
class Object obj where
type Unit obj :: *
unit :: Unit obj
instance (Object obj, Object obj') => Object (obj, obj') where
type Unit (obj, obj') = (Unit obj, Unit obj')
unit = (unit, unit)
Run Code Online (Sandbox Code Playgroud)
我认为目的是相当透明的(尝试定义产品类别).
这给了我:
objs.hs:10:10:
Could not deduce (Unit obj' ~ Unit obj1)
from the context (Object obj, Object obj')
bound by the instance declaration at objs.hs:8:10-56
NB: `Unit' is a type function, and may not be injective
The type variable …Run Code Online (Sandbox Code Playgroud) 我正在尝试学习一些模板Haskell.作为练习,我写的,可以生成诸如函数isLeft和isRight(灵感来自这个问题).这是我谦虚的尝试:
isA connam = do
ConE nam <- connam
nn <- newName "p"
lamE [varP nn] $ caseE (varE nn) [
match (conP nam [wildP]) ( normalB [| True |] ) [],
match wildP ( normalB [| False |] ) []
]
Run Code Online (Sandbox Code Playgroud)
问题是我必须写$(isA [| Left |])而不是更直观isA Left.是否有可能摆脱丑陋的语法?我似乎无法在文档中找到答案.
该函数仅适用于单参数构造函数,但这是另一个问题.
考虑这个例子:
class A
{
void foo();
public:
void bar();
};
template <class> class B
{
B()
{
A a;
a.foo(); // 1
A::bar(); // 2
a.bar(1); // 3
}
};
Run Code Online (Sandbox Code Playgroud)
注意B永远不会被实例化.
clang++报告所有三条标记的行都是错误的.g++(4.8.3)接受行1,2并且仅报告行3.
如果B实例化,请g++愉快地将所有三行报告为错误.
这是一个g++错误吗?有人会这么认为.A不是依赖名称,应在模板定义时正常检查其成员.我看不到细微差别吗?
在使用Haskell FFI到C/C++时,我最近遇到了C++内联函数的问题.也就是说,g ++并不真正内联声明的函数inline,并为它们生成符号.最终,当ghci尝试加载调用内联函数的目标文件时,这会生成链接器错误:
Loading object (static) solveeq.o ... done
Loading object (dynamic) /usr/lib/gcc/x86_64-linux-gnu/4.6/libstdc++.so ... done
final link ... ghc: solveeq.o: unknown symbol `_ZN5Eigen8internal19throw_std_bad_allocEv'
Run Code Online (Sandbox Code Playgroud)
这里,_ZN5Eigen8internal19throw_std_bad_allocEv是inline仅在标题的Eigen C++库中的函数,以某种方式被视为实函数并给出了链接器符号.solveeq.o是我的目标文件,它对该函数进行(间接)调用.环境是Ubuntu 12.04 64bit,ghc 7.4.1.
问题是这样的:我可以extern "C" 用来阻止C++为我自己的函数装饰函数名.但我不能/不应该更改其他人定义的C++标头(原因很明显).在我看来,编译器不应该首先为此内联定义创建一个函数来导致此错误.原因很简单.如果有问题的函数是真正内联的,我不会得到链接器错误.如果编译器变得聪明并决定为它创建一个真正的函数,我会得到这样的错误(或者我在其他地方读到的同一函数的多个定义).所以现在,编译/链接的正确性取决于编译器的情绪.
此外,我认为像这样的链接器问题实际上会破坏仅限标头的C++库(它们具有吸引力),因为现在无法使用它们进行导出extern "C".
这是c ++的设计问题还是仅仅是一个g ++问题?我的问题是,有没有办法阻止c ++编译器或g ++不内联内联函数?例如,是否有一个命令行选项?(修改源代码是不可能的,因为它们是库代码.)
另外,我很好奇C++ STL是如何处理这个问题的.它们也只是标题吗?