你能否分享Boost :: MPL用法的任何实际例子(lambdas除外),只是为了让我更好地理解它的用途和实际应用领域?MPL文档教程有一个维度分析示例,但也许是因为它是一个这样的学术示例,它没有让我感觉到Boost :: MPL以及何时可以有效地使用它.
类型在语义上等效时,隐式转换非常有用.例如,假设两个库以相同的方式实现类型,但在不同的命名空间中.或者只是一种大多数相同的类型,除了一些语义糖在这里和那里.现在,您无法将一种类型传递给设计为使用另一种的函数(在其中一个库中),除非该函数是模板.如果不是,你必须以某种方式将一种类型转换为另一种类型.这应该是微不足道的(或者其他类型在后面都不是那么相同!)但是调用转换显然会使代码膨胀,而且函数调用几乎毫无意义.虽然这样的转换函数实际上可能会复制一些值,但它们从高级"程序员"的角度来看基本上什么都不做.
隐式转换构造函数和运算符显然可以提供帮助,但它们引入了耦合,因此其中一种类型必须知道另一种类型.通常,至少在处理库时,情况并非如此,因为其中一种类型的存在使另一种类型变得冗余.此外,您不能总是更改库.
现在我看到有关如何在用户代码中进行隐式转换的两个选项:
第一个是提供代理类型,它为所有涉及的类型实现转换操作符和转换构造函数(和赋值),并始终使用它.
第二个需要对库进行最小的更改,但允许很大的灵活性:为每个可以在外部选择启用的相关类型添加转换构造函数.
例如,对于类型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向量).
请考虑以下头文件:
// Foo.h
class Foo {
public:
template <typename T>
void read(T& value);
};
Run Code Online (Sandbox Code Playgroud)
我想Foo::read在源文件中显式实例化成员函数模板,包括在boost::mpl::vector:
// Foo.cc
#include <boost/mpl/vector.hpp>
#include <boost/mpl/begin_end.hpp>
#include "Foo.h"
template <typename T>
void Foo::read(T& value) { /* do something */ }
typedef boost::mpl::vector<int, long, float> types;
// template Foo::read<int >(int&);
// template Foo::read<long >(long&);
// template Foo::read<float>(float&);
// instantiate automatically ???
Run Code Online (Sandbox Code Playgroud)
可能吗?谢谢,丹尼尔.
编辑
我找到了一些解决方案 - 似乎Foo::read<T>在结构的构造函数中指定一个指针,然后声明该变量,导致实例化:
// intermezzo
template <typename T> struct Bar {
Bar<T>() {
void (Foo::*funPtr)(T&) = &Foo::read<T>; …Run Code Online (Sandbox Code Playgroud) 通常,我会使用boost::mpl::for_each<>()遍历a boost::mpl::vector,但这需要一个带有模板函数的仿函数,如下所示:
template<typename T> void operator()(T&){T::staticCall();}
我的这个问题是我不希望的物体T被实例化也for_each<>.我根本不需要T参数operator().有没有办法实现这一点,或者替代方法for_each<>是不将类型为T的对象传递给模板函数?
最理想的是,我希望operator()定义如下所示:
template<typename T> void operator()(){T::staticCall();}
当然,我不希望在通话之前对T进行实例化.任何其他提示/建议也欢迎.
我想做这样的事情:
template<int N>
char* foo() {
// return a compile-time string containing N, equivalent to doing
// ostringstream ostr;
// ostr << N;
// return ostr.str().c_str();
}
Run Code Online (Sandbox Code Playgroud)
似乎boost MPL库可能允许这样但我无法弄清楚如何使用它来实现这一点.这可能吗?
我正在尝试创建一个包含给定类型列表的排列的列表.
下面的代码似乎起作用,虽然没有预期的结果,当我使用指定的列表而不是通过从实际输入中删除来生成新列表.下面的permutation_helper和broken_helper之间的区别证明了这一点.
有谁知道为什么mpl::remove在这种情况下似乎没有像预期的那样发挥作用?
#include <boost/mpl/list.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/remove.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/equal.hpp>
namespace mpl = boost::mpl;
struct test_type1 {};
struct test_type2 {};
struct test_type3 {};
template< typename T >
struct permutations;
template <typename value>
struct permutations<mpl::list1< value > >: mpl::list1<mpl::list1< value > > {};
template< typename value, typename T>
struct permutation_helper:
mpl::transform< typename permutations<
mpl::list1<test_type3> >::type,
mpl::push_front< mpl::_1, value> > { };
template< typename value, typename T>
struct broken_helper:
mpl::transform< typename …Run Code Online (Sandbox Code Playgroud) 您好在boost mpl文档中我发现了mpl :: string和以下示例:
typedef mpl::string<'hell','o wo','rld'> hello;
Run Code Online (Sandbox Code Playgroud)
我有点惊讶,因为我认为在C或C++中我们不能在角色之间有多个角色'?
这是正常而有效的吗?
假设我有以下元函数:
template <typename T>
struct make_pair {
using type = std::pair<
typename std::remove_reference<T>::type,
typename std::remove_reference<T>::type
>;
};
Run Code Online (Sandbox Code Playgroud)
相反,它会提高编译速度(或其他)吗?
template <typename T>
struct make_pair {
using without_reference = typename std::remove_reference<T>::type;
using type = std::pair<without_reference, without_reference>;
};
Run Code Online (Sandbox Code Playgroud)
我看到两种可能性:
编译器每次看到它都必须做一些工作typename std::remove_reference<T>::type.使用中间别名具有某种"缓存"行为,这允许编译器只执行一次工作.
编译时性能是根据编译器必须执行的模板实例化的数量来衡量的.因为std::remove_reference<T>::type引用的类型相同std::remove_reference<T>::type,所以在这两种情况下只需要一个模板实例化,因此两个实现都是等效的WRT编译时性能.
我认为B是对的,但我想确定一下.如果答案结果是编译器特定的,我最感兴趣的是知道Clang和GCC的答案.
编辑:
我对测试程序的编译进行了基准测试,以便使用一些数据.测试程序做了类似的事情:
template <typename ...> struct result;
template <typename T>
struct with_cache {
using without_reference = typename std::remove_reference<T>::type;
using type = result<without_reference, ..., without_reference>;
};
template <typename T>
struct without_cache {
using type …Run Code Online (Sandbox Code Playgroud) c++ templates instantiation boost-mpl template-meta-programming
我看到了在C++ 11/14中实现类型列表的两种可能的样式,我很好奇是否有任何理由偏爱另一种.这里概述了第一种技术,并在Boost的MPL库中进行了建模.在这种风格中,您可以定义元"自由函数"(使用声明的顶级),它们接收类型列表并对其进行操作.以下是如何实现std :: transform的元版本,它适用于类型而不是第一种样式中的值:
template <typename... Args>
struct type_list;
namespace impl
{
template <template <typename...> class F, class L>
struct transform_impl;
template <template <typename...> class F, template <typename...> class L, typename... T>
struct transform_impl<F, L<T...>>
{
using type = L<typename F<T>::type...>;
};
}
template <template <typename...> class F, class L>
using transform = typename impl::transform_impl<F, L>::type;
Run Code Online (Sandbox Code Playgroud)
第二种方式是定义元'方法'(使用类型列表结构中的声明).以下是变换在该样式中的外观:
template <typename... Args>
struct type_list {
// ... other 'methods'
template<template<class> class Wrapper>
using transform =
type_list<Wrapper<Args>...>;
// ... …Run Code Online (Sandbox Code Playgroud) 我目前正在使用boost :: mpl对概念样本进行一些证明,并且在理解lambda函数如何使用占位符方面遇到了一些困难.
我意识到我可以将metafunctions包装在元函数类中,以使更高阶函数能够访问嵌套的apply函数,并且已经意识到你可以通过使用mpl :: lambda包装允许占位符的元函数来避免这种努力.
这实际上是如何工作的?我无法将我的头包裹在lamda和占位符实际上在封面下做什么.