您可以利用惰性求值表达式模板。
AFAIK 绑定表达式恰好属于该家族(Boost Proto 表达式、Spirit Grammar 解析表达式等也是如此)。
更新终于让我一起行动了。但是,它仅适用于具有重载 operator()的可调用对象。我想你可以用这样的东西作为胶水吗?
- 我现在展示了 C++03 和 C++11 的概念证明,它们可能有助于围绕这个构建胶函子
- C++03几乎等价(参见
// TODO
代码中的)
- C++03 版本依赖于 Boost Typeof 和 Boost Bind(有关多态函数对象的结果类型的背景信息,请参见Boost Utility 文档)
result_of
- 两个版本都在 IdeOne 上提供
这是 C++11 演示(下)到 C++03 + Boost 的部分移植:
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/typeof/typeof.hpp>
struct overloaded
{
typedef int result_type;
int operator()(const std::string& s) const { return 1; }
int operator()(double d) const { return 2; }
};
struct factory
{
template <typename T> struct result { typedef BOOST_TYPEOF_TPL(boost::bind(overloaded(), T())) type; };
template <typename T>
typename result<T>::type operator()(const T& t) const
{
return boost::bind(overloaded(), t);
}
};
int main()
{
overloaded foo;
// based on local bind expression:
BOOST_AUTO(unresolved, boost::bind(foo, _1));
std::cout << unresolved("3.14") << std::endl; // should print 1
std::cout << unresolved(3.14) << std::endl; // should print 2
// based on a factory function template
factory makefoo;
std::string str("3.14"); // TODO get rid of this explicit instanciation?
std::cout << makefoo(str)() << std::endl; // should print 1
std::cout << makefoo(3.14)() << std::endl; // should print 2
}
作为一个简单的例子,这应该可以正常工作:
#include <string>
#include <iostream>
#include <functional>
using namespace std::placeholders;
struct overloaded
{
int operator()(const std::string& s) const { return 1; }
int operator()(double d) const { return 2; }
};
template <typename T>
auto makefoo(const T& t) -> decltype(std::bind(overloaded(), t))
{
return std::bind(overloaded(), t);
}
int main()
{
overloaded foo;
// based on local bind expression:
auto unresolved = std::bind(foo, _1);
std::cout << unresolved(3.14) << std::endl; // should print 2
std::cout << unresolved("3.14") << std::endl; // should print 1
// based on a factory function template
std::cout << makefoo(3.14)() << std::endl; // should print 2
std::cout << makefoo("3.14")() << std::endl; // should print 1
}