显然,你不能void在格式良好的程序中有一个类型的实例,所以类似下面的声明就不会编译:
std::tuple<void, double, int> tup;
Run Code Online (Sandbox Code Playgroud)
但是,只要我们严格处理类型而不是对象,似乎没有问题.例如,我的编译器(GCC)让我说:
typedef std::tuple<void, double, int> tuple_type;
Run Code Online (Sandbox Code Playgroud)
这对我来说很有意思,因为看起来使用C++ 0x我们可以用它std::tuple来执行许多早期需要boost::mpl库的元编程技巧.例如,我们可以使用std::tuple创建类型的向量.
例如,假设我们要创建表示函数签名的类型向量:
我们可以说:
template <class R, class... Args>
struct get_function_signature;
template <class R, class... Args>
struct get_function_signature<R(*)(Args...)>
{
typedef std::tuple<R, Args...> type;
};
Run Code Online (Sandbox Code Playgroud)
这似乎有效,即使函数签名具有void类型,只要我们从未实际实例化实例get_function_signature<F>::type.
但是,C++ 0x对我来说仍然是新手,当然所有实现仍然有点实验性,所以我对此有点不安.我们真的可以std::tuple用作元编程的类型向量吗?
从列表中删除重复项最方便的"Pythonic"方法基本上是:
mylist = list(set(mylist))
Run Code Online (Sandbox Code Playgroud)
但是假设您计算重复项的标准取决于包含在其中的对象的特定成员字段mylist.
好吧,一个解决方案就是定义__eq__和__hash__使用对象mylist,然后经典list(set(mylist))将起作用.
但有时您的要求需要更多的灵活性.能够创建动态lambda以使用自定义比较例程以不同方式识别重复项将非常方便.理想情况下,例如:
mylist = list(set(mylist, key = lambda x: x.firstname))
Run Code Online (Sandbox Code Playgroud)
当然,这实际上并不起作用,因为set构造函数不采用比较函数,并且还set需要可散列密钥.
那么实现类似的东西的最接近的方法是什么,以便您可以使用任意比较函数删除重复项?
我已经阅读了之前有关使用的reinterpret_cast各种问题,并且我还阅读了C++标准中的相关措辞.本质上,它归结为指针到指针reinterpret_cast操作的结果不能安全地用于除了被回送到原始指针类型之外的任何东西.
然而,在实践中,大多数现实世界的使用reinterpret_cast似乎都是基于(错误的)假设,即a reinterpret_cast与C风格的演员表相同.例如,我见过很多的代码,它使用reinterpret_cast从投char*来unsigned char*的字符集转换程序的目的.这是完全无害的,但严格来说,它不是便携式-有没有保证,一个reinterpret_cast来自char*于unsigned char*当您尝试取消引用不会崩溃您的程序unsigned char*指针.
根据标准,似乎唯一的其他实际用途reinterpret_cast有任何真正的保证,是从指针转换为整数,反之亦然.
然而,在许多情况下,我们希望(并且应该能够)在不同的指针类型之间安全地进行转换.例如:uint16_t*到新的C++ 0x char16_t*,或者实际上是指向与原始类型相同大小/对齐的基本数据类型的任何指针.然而,reinterpret_cast并不保证这应该起作用.
问题:如何安全地在指向相同大小/对齐的基本数据类型的指针之间进行转换,例如char*- > unsigned char*?既然reinterpret_cast似乎并不保证这实际上有效,那么C风格的演员是唯一安全的选择吗?
我早就知道GCC使用COW(Copy-On-Write)std::string,因此无法std::string在多线程程序中使用.但据我所知,C++ 11禁止使用COW实现,因为线程现在由标准定义,并且移动语义几乎已经过时了对COW的需求.
现在,GCC 4.6实现了大量的C++ 11标准.但似乎实现仍在使用COW语义.在我写的多线程应用程序中,随机发生的神秘seg-fault引起了我的注意.事实上,我已通过以下测试代码证实这是一个COW问题:
#include <iostream>
#include <string>
#include <cassert>
#include <thread>
using namespace std;
int main()
{
std::string orig = "abc";
std::string copy = orig;
std::cout << (void*) orig.data() << ", " << (void*) copy.data() << endl;
assert(orig.data() == copy.data());
}
Run Code Online (Sandbox Code Playgroud)
编辑:注意<thread>这里包含标题,证明这是一个C++ 11程序.这里有一个连接到ideone确认我在说什么,(至少对于GCC 4.5.1,ideone使用)
我不记得为什么,但由于某种原因,我的印象是std=c++0x旗帜会消除COW语义,但事实并非如此.即使使用--std = c ++ 0x标志,上述代码中的断言也是成功的. 所以基本上,从GCC 4.6开始,std::string在多线程应用程序中仍然无法使用.
有没有办法禁用COW语义?或者我std::vector<char>现在需要使用,直到GCC修复此问题?
(有些)过时的文章探讨了decltype与SFINAE一起使用的方法,以检测某种类型是否支持某些运算符,例如==或<.
以下是检测类是否支持<运算符的示例代码:
template <class T>
struct supports_less_than
{
static auto less_than_test(const T* t) -> decltype(*t < *t, char(0))
{ }
static std::array<char, 2> less_than_test(...) { }
static const bool value = (sizeof(less_than_test((T*)0)) == 1);
};
int main()
{
std::cout << std::boolalpha << supports_less_than<std::string>::value << endl;
}
Run Code Online (Sandbox Code Playgroud)
这输出true,因为当然std::string支持<操作员.但是,如果我尝试将它与不支持<运算符的类一起使用,我会收到编译器错误:
error: no match for ‘operator<’ in ‘* t < * t’
Run Code Online (Sandbox Code Playgroud)
所以SFINAE不在这里工作.我在GCC 4.4和GCC …
最近,我很好奇浮点数的哈希算法是如何工作的,所以我查看了源代码boost::hash_value.事实证明这很复杂.实际实现循环遍历基数中的每个数字并累积哈希值.与整数散列函数相比,它涉及更多.
我的问题是:为什么浮点哈希算法会更复杂?为什么不将浮点值的二进制表示形式哈希,就好像它是一个整数?
喜欢:
std::size_t hash_value(float f)
{
return hash_value(*(reinterpret_cast<int*>(&f)));
}
Run Code Online (Sandbox Code Playgroud)
我意识到float不能保证与int所有系统上的大小相同,但是可以使用一些模板元程序来处理这种事情,以推断出与其相同大小的整数类型float.那么引入一个专门针对浮点类型操作的完全不同的哈希函数有什么好处呢?
我总是尝试在任何地方使用STL算法,而不是编写手动循环.但是,我很难理解std::accumulate通常有用的方法.每当我需要计算总和或平均值时,我几乎总是求助于手动循环,因为我很难std::accumulate做到我需要的东西.
问题是我很少有一个简单的整数向量需要求和.通常,我想使用特定的成员变量对一个对象数组求和.是的,我知道有一个版本std::accumulate需要一个BinaryFunction,但我看到的问题是这个函数需要采用两个类型的值T,其中T是sum的类型,而不是操作数的类型.我无法理解这是如何有用的.
考虑一个我认为很常见的案例.我有以下课程:
struct Foo
{
Foo(int cost_, int id_) : cost(cost_), id(id_)
{ }
int cost;
int id;
};
Run Code Online (Sandbox Code Playgroud)
现在,假设我想使用计算Foo对象数组的总和Foo::cost.
我想说:
std::vector<Foo> vec;
// fill vector with values
int total_cost = std::accumulate(vec.begin(), vec.end(), 0, sum_cost);
Run Code Online (Sandbox Code Playgroud)
并sum_cost定义为:
int sum_cost(const Foo& f1, const Foo& f2)
{
return f1.cost + f2.cost;
}
Run Code Online (Sandbox Code Playgroud)
问题是,这不起作用,因为std::accumulate需要一个BinaryFunction,它接收生成的sum类型的两个实例- 在这种情况下只是int.但这对我有什么用呢?如果我的BinaryFunction接受两个ints,我不能指定我想要求 …
Python C API函数PyEval_EvalCode允许您执行已编译的Python代码.我想执行一段Python代码,就像它在函数范围内执行一样,因此它有自己的局部变量字典,不会影响全局状态.
这看起来很容易,因为PyEval_EvalCode您可以提供全局和本地词典:
PyObject* PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
我遇到的问题与Python如何查找变量名称有关.考虑以下代码,我执行PyEval_EvalCode:
myvar = 300
def func():
return myvar
func()
Run Code Online (Sandbox Code Playgroud)
这个简单的代码实际上会引发错误,因为Python无法myvar从内部找到变量func.即使myvar在外部作用域中的本地字典中,Python也不会将其复制到内部作用域中的本地字典中.原因如下:
每当Python查找变量名时,首先检查locals,然后检查globals,最后检查builtins.在模块范围,locals并且globals是SAME字典对象.因此,声明x = 5在模块范围内将放置x在该locals字典,这也是globals字典.现在,在函数范围内x找不到需要查找的模块作用域定义x的函数locals,因为Python不会将模块作用域本地复制到函数作用域本地.但是,这通常是没有问题的,因为它可以找到x在globals.
x = 5
def foo():
print(x) # This works because 'x' in …Run Code Online (Sandbox Code Playgroud) 鉴于以下两个函数,我希望在传递它时调用第一个重载std::pair<const char*, std::size_t>,因为它比泛型更具体T.
void foo(const std::pair<const char*, std::size_t>& p)
{
std::cout << "pair" << std::endl;
}
template <class T>
void foo(const T& v)
{
std::cout << "generic" << std::endl;
}
int main()
{
const char* s = "abc";
foo(std::make_pair(s, std::size_t(3)));
}
Run Code Online (Sandbox Code Playgroud)
但是,该计划输出:
generic
Run Code Online (Sandbox Code Playgroud)
为什么调用第二个重载,而不是显式占用的重载pair?
这是编译器问题吗?我现在正好使用一个非常古老的编译器(GCC 4.1.2).
嗯......它可能是一个编译器问题:
GTK允许您设置超时g_timeout_add.就像g_signal_connect,g_timeout_add函数返回一个表示超时的id.那么,有没有办法使用id 取消超时?通过文档查看,我没有看到任何取消超时事件的方法,但我认为必须有一些方法,否则id返回值的重点是g_timeout_add什么?
那么,有没有办法取消超时事件,或者这只是需要通过设置"取消标志"手动处理的东西,可以在用户提供的超时处理函数中进行检查?