类型在语义上等效时,隐式转换非常有用.例如,假设两个库以相同的方式实现类型,但在不同的命名空间中.或者只是一种大多数相同的类型,除了一些语义糖在这里和那里.现在,您无法将一种类型传递给设计为使用另一种的函数(在其中一个库中),除非该函数是模板.如果不是,你必须以某种方式将一种类型转换为另一种类型.这应该是微不足道的(或者其他类型在后面都不是那么相同!)但是调用转换显然会使代码膨胀,而且函数调用几乎毫无意义.虽然这样的转换函数实际上可能会复制一些值,但它们从高级"程序员"的角度来看基本上什么都不做.
隐式转换构造函数和运算符显然可以提供帮助,但它们引入了耦合,因此其中一种类型必须知道另一种类型.通常,至少在处理库时,情况并非如此,因为其中一种类型的存在使另一种类型变得冗余.此外,您不能总是更改库.
现在我看到有关如何在用户代码中进行隐式转换的两个选项:
第一个是提供代理类型,它为所有涉及的类型实现转换操作符和转换构造函数(和赋值),并始终使用它.
第二个需要对库进行最小的更改,但允许很大的灵活性:为每个可以在外部选择启用的相关类型添加转换构造函数.
例如,对于类型A添加构造函数:
template <class T> A(
const T& src,
typename boost::enable_if<conversion_enabled<T,A>>::type* ignore=0
)
{
*this = convert(src);
}
Run Code Online (Sandbox Code Playgroud)
和一个模板
template <class X, class Y>
struct conversion_enabled : public boost::mpl::false_ {};
Run Code Online (Sandbox Code Playgroud)
默认情况下禁用隐式转换.
然后要启用两种类型之间的转换,请专门化模板:
template <> struct conversion_enabled<OtherA, A> : public boost::mpl::true_ {};
Run Code Online (Sandbox Code Playgroud)
并实现一个convert可以通过ADL找到的函数.
我个人更喜欢使用第二种变体,除非有强烈的反对意见.
现在回答实际问题:关联隐式转换类型的首选方法是什么?我的建议是好主意吗?两种方法都有任何缺点吗?允许这样的转换是危险的吗?如果库类实现者通常会提供第二种方法,那么它们的类型很可能会被软件复制,而这些软件很可能与它们一起使用(我在考虑使用3d渲染中间件,其中大多数软件包实现了3D向量).
我试图以优雅的方式将当前时间作为"YYYY-MM-DD-HH-MM-SS"格式化字符串.我可以从Boost的"Date Time"库获取ISO格式的当前时间,但它有其他分隔字符串,这对我不起作用(我在文件名中使用它).当然我可以直接替换分隔字符串,但感觉有一种更好的方法可以使用日期时间的格式化选项.有这样的方式,如果有的话,我该如何使用它?
我发现自己编写的代码基本上是这样的:
using boost::system::error_code;
socket.async_connect(endpoint, [&](error_code Error)
{
if (Error)
{
print_error(Error);
return;
}
// Read header
socket.async_read(socket, somebuffer, [&](error_code Error, std::size_t N)
{
if (Error)
{
print_error(Error);
return;
}
// Read actual data
socket.async_read(socket, somebuffer, [&](error_code Error, std::size_t N)
{
// Same here...
});
});
};
Run Code Online (Sandbox Code Playgroud)
所以基本上我在回调中的回调中嵌套回调,而逻辑很简单并且是"线性的".
是否有更优雅的方式来编写它,以便代码是本地的和有序的?
这两个未命名的命名空间的嵌套用法之间是否存在功能差异:
namespace A { namespace {
void foo() {/*...*/}
}}
Run Code Online (Sandbox Code Playgroud)
和
namespace { namespace A {
void foo() {/*...*/}
}}}
Run Code Online (Sandbox Code Playgroud)
据我所知,两个foos都将获得每个编译单元的内部唯一标识符,并且可以使用A::foo- 但是有一个微妙的或不那么微妙的区别,我没有看到?
我有一系列值,我想传递给一(iterator begin, iterator end)对函数.但是,我只希望处理原始序列中的每个第二个元素.
有没有一种很好的方法使用Standard-Lib/Boost创建一个迭代器外观,允许我传入原始序列?我认为这样的简单事情已经在boost迭代器或范围库中,但我没有找到任何东西.
或者我错过了另一个完全明显的方法来做到这一点?当然,我知道我总是可以选择将值复制到另一个序列,但这不是我想要做的.
编辑:我知道filter_iterator,但过滤值 - 它不会改变迭代进展的方式.
这保证是有效的:
struct A
{
struct Gold {};
};
struct B : public A
{
typedef Gold BaseGold;
struct Gold {};
};
struct C : public B
{
typedef Gold BaseGold;
struct Gold {};
};
static_assert(is_same<B::BaseGold, A::Gold>::value, "Not the right treasure!");
static_assert(is_same<C::BaseGold, B::Gold>::value, "Not the right treasure!");
Run Code Online (Sandbox Code Playgroud)
它似乎适用于VS2010.显然它依赖于微妙的声明顺序/名称查找规则,所以我想知道标准在这个问题上说了什么......
我有一个依赖std::shared_ptr很多的API(一个特定的GUI库),即它们通常用作函数参数并存储在其他对象中.例如,容器小部件(例如拆分器和框)将其子小部件存储在shared_ptrs中.现在我想通过luabind将此API映射到Lua.在理想的世界中,Luabind将在shared_ptrs中创建新对象,并允许我将这些对象直接传递给采用shared_ptr参数的函数.这似乎适用于单个类,例如:
luabind::class_<Button, std::shared_ptr<Button>>("Button")
Run Code Online (Sandbox Code Playgroud)
虽然我这样声明,但我可以公开和使用像void foo(std::shared_ptr<Button> const&).
现在,luabind手册提到为了使用类的层次结构,我必须对层次结构中的所有类使用相同的shared_ptr模板实例,例如
luabind::class_<BaseWidget, std::shared_ptr<BaseWidget>>("BaseWidget"),
luabind::class_<Button, BaseWidget, std::shared_ptr<BaseWidget>>("Button")
Run Code Online (Sandbox Code Playgroud)
现在我再也无法打电话了foo- 它将无法从Lua找到该功能.我可以以某种方式让luabind继续支持shared_ptrs中的传递按钮吗?此外,我想知道为什么luabind要求您对层次结构中的所有类使用相同的智能指针,而不是它们只能转换为基类指针.
我正在尝试使用循环引用boost::shared_ptr,并设计了以下示例:
class A{ // Trivial class
public:
i32 i;
A(){}
A(i32 a):i(a){}
~A(){
cout<<"~A : "<<i<<endl;
}
};
shared_ptr<A> changeI(shared_ptr<A> s){
s->i++;
cout<<s.use_count()<<'\n';
return s;
}
int main() {
shared_ptr<A> p1 = make_shared<A>(3);
shared_ptr<A> p2 = p1;
shared_ptr<A> p3 = p2;
shared_ptr<A> p4 = p3;
p1 = p4; // 1) 1st cyclic ref.
cout<<p1.use_count()<<'\n';
p1 = changeI(p4); // 2) 2nd cyclic ref.
cout<<p1.use_count()<<'\n';
// putchar('\n');
cout<<endl;
}
Run Code Online (Sandbox Code Playgroud)
哪个输出
4
5
4
~A : 4
Run Code Online (Sandbox Code Playgroud)
是不是我误解了所提到的循环引用boost::shared_ptr?因为,我预计间接引用的不同输出思维p1 …
四面体网格中的点位置是否有任何经过验证的数据结构,其中四面体都是不相交的,但彼此"接触"?即大多数面孔都是正好两个四面体的面孔.
按位置我的意思是我想找出给定点位于哪个四面体中,或者它是否位于任何四面体中.
到目前为止,我尝试过:
一个简单的KD树.这对我的需求来说太慢了,因为平均树深非常高,我仍然有很多单独的四面体在每片叶子中进行测试.
一个网格,包含每个单元格的所有交叉四面体.这似乎工作得更好,但仍然不够快.首先,网格包含许多空单元格,因为我的整体网格不是非常"四四方方".其次,大多数实际上含有四面体的细胞确实含有大量细胞(10+).我想这是因为很多四面体共享每个顶点,一旦顶点在一个单元格中,所有相邻的四面体也是如此.
关于输入数据的一些进一步信息:网格通常不是凸的并且可以具有孔或内含物.虽然最后两个有点不太可能,但我必须处理它们,如果没有(昂贵和复杂的?)预处理,这使得"行走"变得不可能.
有没有办法将c ++ 0x lambda的签名,结果和参数类型推断为Boost.MPL序列,例如boost::mpl::vector?例如,对于lambda
[]( float a, int b ) -> void { std::cout << a << b << std::endl; }
Run Code Online (Sandbox Code Playgroud)
我想得到一个boost::mpl::vector<void,float,int>.
c++ ×9
boost ×2
boost-mpl ×2
c++11 ×2
lambda ×2
shared-ptr ×2
algorithm ×1
boost-asio ×1
enable-if ×1
inheritance ×1
lua ×1
luabind ×1
name-lookup ×1
namespaces ×1
stl ×1
weak-ptr ×1