对于某些整数类型,即使浮点值远远超出整数的可表示范围,如何找到最接近某个浮点类型值的值.
或者更确切地说:
我们F是一个浮点型(可能是float,double或long double).让I是一个整数类型.
假设两个F并I有有效的专业化std::numeric_limits<>.
给定可表示的值F,并且仅使用C++ 03,如何找到最接近的可表示值I?
我追求的是一个纯粹,高效且线程安全的解决方案,除了C++ 03所保证的以外,它不会对平台做任何假设.
如果不存在这样的解决方案,是否可以使用C99/C++ 11的新功能找到一个?
lround()由于报告域错误的非平凡方式,使用C99似乎是有问题的.这些域错误是否可以以便携式和线程安全的方式捕获?
注意:我知道Boost可能通过其boost::numerics::converter<>模板提供解决方案,但由于其高复杂性和冗长性,我无法从中提取必需品,因此我无法检查他们的解决方案是否成功超出C++ 03的假设.
下面的天真方法失败了,因为I(f)当C++ 03的整数部分f不是可表示的值时,结果是未定义的I.
template<class I, class F> I closest_int(F f)
{
return I(f);
}
Run Code Online (Sandbox Code Playgroud)
然后考虑以下方法:
template<class I, class F> I closest_int(F f)
{
if (f < std::numeric_limits<I>::min()) return std::numeric_limits<I>::min();
if (std::numeric_limits<I>::max() < f) return std::numeric_limits<I>::max();
return I(f);
} …Run Code Online (Sandbox Code Playgroud) 我一直在评估各种智能指针实现(哇,有很多),在我看来,大多数可以分为两大类:
1)此类别对引用的对象使用继承,以便它们具有引用计数,并且通常实现up()和down()(或它们的等价物).IE,要使用智能指针,您指向的对象必须从ref实现提供的某些类继承.
2)此类别使用辅助对象来保存引用计数.例如,不是将智能指针指向对象,而是实际指向此元数据对象...谁具有引用计数以及up()和down()实现(并且通常为指针提供一种机制)获取指向的实际对象,以便智能指针可以正确实现operator - >()).
现在,1有一个缺点,它强制你想引用的所有对象计数从一个共同的祖先继承,这意味着你不能使用它来引用你无法控制源代码的计数对象至.
2有一个问题,因为计数存储在另一个对象中,如果你有一个指向现有引用计数对象的指针被转换为引用的情况,你可能有一个错误(IE,因为计数不在实际的对象,新的引用没有办法得到计数...引用ref复制构造或赋值是好的,因为它们可以共享count对象,但如果你必须从指针转换,你'完全被冲洗了)...
现在,正如我所理解的那样,boost :: shared_pointer使用了机制2,或类似的东西......那就是说,我不能完全决定哪个更糟糕!我只使用机制1,在生产代码中......有没有人有这两种风格的经验?或许还有另一种方式比这两种方式更好?
注意:这个问题最初是在2012年提出的.在说明decltype符由任何主要编译器完全实现之前.除非您只能访问C++ 03,否则不应该查看此代码.现在所有符合C++ 11标准的主要编译器都支持decltype.
有没有一种简单的方法来检索成员的类型?
在C++ 03中
struct Person
{
std::string name;
int age;
double salary;
};
int main()
{
std::vector<Person> people; // get a vector of people.
std::vector<GET_TYPE_OF(Person::age)> ages;
ages.push_back(people[0].age);
ages.push_back(people[10].age);
ages.push_back(people[13].age);
}
Run Code Online (Sandbox Code Playgroud)
我实际上是这样做的(即稍微懒惰):
#define BuildType(className, member, type) \
struct className ## member: TypeBase<className, type> \
{ \
className ## member() \
: TypeBase<className, type>(#member, &className::member) \
{} \
}
BuildType(Person, name, std::string);
BuildType(Person, age, int);
BuildType(Person, salary, double);
typedef boost::mpl::vector<Personname, Personage, Personsalary> FunckyMTPMap;
Run Code Online (Sandbox Code Playgroud)
但是,不必强制用户指定我想要编译器以实用方式生成它的成员的类型. …
我想为我当前的问题使用一组位标志.这些标志(很好地)被定义为一部分enum,但是据我所知,当你OR从枚举中获得两个值时,OR操作的返回类型具有类型int.
我目前正在寻找的是一种解决方案,它允许位掩码的用户保持类型安全,因此我创建了以下重载 operator |
enum ENUM
{
ONE = 0x01,
TWO = 0x02,
THREE = 0x04,
FOUR = 0x08,
FIVE = 0x10,
SIX = 0x20
};
ENUM operator | ( ENUM lhs, ENUM rhs )
{
// Cast to int first otherwise we'll just end up recursing
return static_cast< ENUM >( static_cast< int >( lhs ) | static_cast< int >( rhs ) );
}
void enumTest( ENUM v )
{
}
int …Run Code Online (Sandbox Code Playgroud) 我目前正在考虑是否更喜欢名称空间枚举或命名空间的静态组的问题.什么应该是默认选择,为什么?
namespace Direction
{
enum Direction
{
north,
east,
south,
west,
};
}
Run Code Online (Sandbox Code Playgroud)
namespace Direction
{
static const unsigned char north = 0;
static const unsigned char east = 1;
static const unsigned char south = 2;
static const unsigned char west = 3;
}
Run Code Online (Sandbox Code Playgroud)
两者都有其优点和缺点.
一些类型的安全:
void foo(Direction dir); // the compiler won't allow you to just pass an int or a value of an unrelated enum without explicitly casting it
Run Code Online (Sandbox Code Playgroud)类型安全性相当有限:
enum A …Run Code Online (Sandbox Code Playgroud)假设我有一个C容器(例如MyContainer),其中包含的对象存储为void*指针.迭代此容器元素的唯一方法是通过两个接口函数:
getFirstElem(MyContainer const&, void*):输出容器的第一个元素.getNextElem(MyContainer const&, void*):输出容器的下一个元素.我想编写一个泛型函数,它通过上面提到的接口函数遍历这个C容器的元素,并将它们的值复制到C++容器中(例如std::vector).
到目前为止我做了什么:
template<typename OutputIterator>
void
copy_container(MyContainer const &cont, OutputIterator first) {
typename std::iterator_traits<OutputIterator>::value_type elem;
if(getFirstElem(cont, &elem)) {
do {
*first = elem;
++first;
} while(getNextElem(cont, &elem))
}
}
Run Code Online (Sandbox Code Playgroud)
上面的示例适用于普通迭代器.但是,它无法使用输出迭代器进行编译(例如,copy_container(cont, std::back_inserter(myvector));).
原因是在参数类型是输出迭代器的情况下std::iterator_traits::value_type导致结果void.
有没有办法让这个泛型函数也适用于输出迭代器?
我知道在C++ 11中它可以通过使用decltype(例如decltype(*first))来完成,但我对C++ 11之前的解决方案特别感兴趣,因为我使用旧的C++编译器(gcc v4.4.7).
干杯和hth.- Alf在这个答案中发表评论说,与C++ 98相比,值初始化可以说是C++ 03的一个新特性.我想知道他的意思.
是值初始化的C++ 98的一部分?它是出现在概念中而不是名义上吗?为什么它被添加到C++ 03标准中?
我有'03标准的副本,但不是'98标准.这是默认初始化和值初始化的定义.
默认初始化T类型的对象意味着:
- 如果T是非POD类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
- 如果T是数组类型,则每个元素都是默认初始化的;
- 否则,对象被零初始化.
对值类型T的对象进行值初始化意味着:
- 如果T是具有用户声明的构造函数(12.1)的类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
- 如果T是没有用户声明的构造函数的非联合类类型,则T的每个非静态数据成员和基类组件都是值初始化的;
- 如果T是数组类型,则每个元素都是值初始化的;
- 否则,对象被零初始化
我的猜测是'98有默认初始化但不是值初始化,并且两者之间存在一些关键差异.说实话,我在解析这里的标准时遇到了麻烦,我不明白这些定义之间的区别.
我有一个const std::stringstream想要找出其底层字符串缓冲区中有多少字节的愿望.
我不能seekg到最后,tellg然后seekg重新开始,因为这些操作都不可用const.
我不想得到str().size()因为str()返回副本,这可能不是一个微不足道的数据量.
我有什么好的选择吗?
(流本身const只是因为它是另一种类型的成员而呈现给我,并且我收到const对该类型对象的引用.该流表示"文档"的内容,其封装对象表示CGI响应我试图Content-Length从内部生成准确的HTTP标题行operator<<(std::ostream&, const cgi_response&).)
std::size_t通常用于数组索引和循环计数.根据定义,std::size_t是sizeof运算符以及sizeof...运算符和alignof运算符的结果的无符号整数类型(自C++ 11起).它在以下标题中定义:
<cstddef><cstdio><cstdlib><cstring><ctime><cwchar>据我了解,这些运算符返回的类型是实现定义的.
我想要的是定义一个自定义size_t,以避免从.cpp我的文件中的上述任何标题中提取不必要的东西,因为在我的文件中我只需要std::size_t.
在C++ 11及更高版本中,我认为我可以使用以下别名:
using size_t = decltype(sizeof(1));
Run Code Online (Sandbox Code Playgroud)
但是,我想以size_t便携/跨平台的方式为C++ 11之前的编译器定义一种类型.
那么有一种可移植的方式来定义size_t前C++ 11吗?
标题中的问题可能听起来微不足道,所以我最好用一些代码解释我想要做什么......
在C++ 11中,我可以这样做:
#include <iostream>
namespace X {
enum class FOO { A,B };
}
template <typename T> void foo(T t) {
if (t == T::A) { std::cout << "A"; }
}
int main() {
foo(X::FOO::A);
}
Run Code Online (Sandbox Code Playgroud)
这里重要的一点是,模板foo不需要知道枚举声明的名称空间.我可以如叫foo(Y::FOO::B)(前提是有一个enum class叫做FOO命名空间Y为会员A和B).
现在的问题是:如何使用普通的旧枚举(只有C++ 98的东西)?
这有效:
#include <iostream>
namespace X {
enum FOO { A,B };
}
template <typename T> void foo(T t) {
if (t == X::A) { std::cout …Run Code Online (Sandbox Code Playgroud)