如何将 boost::hana::unpack 与构造函数一起使用,而不是函数?
How to use boost::hana::unpack with the constructor, instead of function?
给定此示例代码,如何使用pars
调用构造函数创建Foo2D
对象?
#include <boost/hana/tuple.hpp>
#include <boost/hana/unpack.hpp>
class Foo2D {
public:
Foo2D(int x, int y):m_x(x), m_y(y) {}
private:
int m_x;
int m_y;
};
int main() {
auto pars = boost::hana::make_tuple(10, 20);
Foo2D foo1(10, 20); //my intention
Foo2D foo2 = boost::hana::unpack(pars, Foo2D); //fails
}
构造函数不是函数或函子。您可以使用 lambda 或常规函数:
boost::hana::unpack(pars,
[](auto&&... args) {
return Foo2D(std::forward<decltype(args)>(args)...);
});
template<class T>
constexpr auto ctor = [](auto&&...args)
noexcept(noexcept(T{ decltype(args)(args)... }))
-> decltype( T{ decltype(args)(args)... } )
{
return T{ decltype(args)(args)... };
};
现在:
Foo2D foo2 = boost::hana::unpack(pars, ctor<Foo2D>);
应该可以。
或:
// Object that represents constructing an object of type T:
template<class T>
struct ctor_t {
template<class...Args>
constexpr auto operator()(Args&&...args) const
// propogate noexcept:
noexcept(noexcept(T{ std::forward<Args>(args)... }))
// SFINAE friendly:
-> decltype( T{ std::forward<Args>(args)... } )
{
// notice this expression is repeated twice above:
return T{ std::forward<Args>(args)... };
}
template<class A0, class...Args>
constexpr auto operator()(std::initializer_list<A0> il, Args&&...args) const
noexcept(noexcept( T{ il, std::forward<Args>(args)... } ))
-> decltype(T{ il, std::forward<Args>(args)... })
{
return T{ il, std::forward<Args>(args)... };
}
constexpr ctor_t() {} // some compilers require this
template<class...Args>
constexpr (*operator T() const)(Args...) const {
return +[](Args...args)->T {
return ctor_t<T>{}(std::forward<Args>(args)...);
};
}
explicit operator bool() const = delete;
};
template<class T>
constexpr ctor_t<T> ctor{};
如果你害怕lambda版本。此版本还支持前导初始化列表和固定签名的隐式转换为工厂函数指针。
Live example。测试代码:
// construct an int 7:
auto x = ctor<int>( 7 );
std::cout << x << "\n";
// get a pointer to a constructor function
// that constructs an int from a short:
int(* pf)(short) = ctor<int>;
// run it:
std::cout << pf(0) << "\n";
给定此示例代码,如何使用pars
调用构造函数创建Foo2D
对象?
#include <boost/hana/tuple.hpp>
#include <boost/hana/unpack.hpp>
class Foo2D {
public:
Foo2D(int x, int y):m_x(x), m_y(y) {}
private:
int m_x;
int m_y;
};
int main() {
auto pars = boost::hana::make_tuple(10, 20);
Foo2D foo1(10, 20); //my intention
Foo2D foo2 = boost::hana::unpack(pars, Foo2D); //fails
}
构造函数不是函数或函子。您可以使用 lambda 或常规函数:
boost::hana::unpack(pars,
[](auto&&... args) {
return Foo2D(std::forward<decltype(args)>(args)...);
});
template<class T>
constexpr auto ctor = [](auto&&...args)
noexcept(noexcept(T{ decltype(args)(args)... }))
-> decltype( T{ decltype(args)(args)... } )
{
return T{ decltype(args)(args)... };
};
现在:
Foo2D foo2 = boost::hana::unpack(pars, ctor<Foo2D>);
应该可以。
或:
// Object that represents constructing an object of type T:
template<class T>
struct ctor_t {
template<class...Args>
constexpr auto operator()(Args&&...args) const
// propogate noexcept:
noexcept(noexcept(T{ std::forward<Args>(args)... }))
// SFINAE friendly:
-> decltype( T{ std::forward<Args>(args)... } )
{
// notice this expression is repeated twice above:
return T{ std::forward<Args>(args)... };
}
template<class A0, class...Args>
constexpr auto operator()(std::initializer_list<A0> il, Args&&...args) const
noexcept(noexcept( T{ il, std::forward<Args>(args)... } ))
-> decltype(T{ il, std::forward<Args>(args)... })
{
return T{ il, std::forward<Args>(args)... };
}
constexpr ctor_t() {} // some compilers require this
template<class...Args>
constexpr (*operator T() const)(Args...) const {
return +[](Args...args)->T {
return ctor_t<T>{}(std::forward<Args>(args)...);
};
}
explicit operator bool() const = delete;
};
template<class T>
constexpr ctor_t<T> ctor{};
如果你害怕lambda版本。此版本还支持前导初始化列表和固定签名的隐式转换为工厂函数指针。
Live example。测试代码:
// construct an int 7:
auto x = ctor<int>( 7 );
std::cout << x << "\n";
// get a pointer to a constructor function
// that constructs an int from a short:
int(* pf)(short) = ctor<int>;
// run it:
std::cout << pf(0) << "\n";