2

我正在尝试创建一个与 boost::any 一起使用的概念。这个概念应该说一个类具有带有签名的 ha 成员函数void templateFunction(T t)。我已经让它编译和工作正常,但一次只能用于一种类型。我想做的事是不可能的吗?

#include <iostream>

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/member.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/any.hpp>

using namespace std;
namespace mpl = boost::mpl;
using namespace boost::type_erasure;

class Foo
{
    public:

        template <class T>
        void templateFunction(T t)
        {
            cout << t << endl;
        }
};

template<class C, class T>
struct has_template_function
{
    static void apply(C& cont, const T& arg) { cont.templateFunction(arg); }
};

namespace boost
{
    namespace type_erasure
    {
        template<class C, class T, class Base>
        struct concept_interface<has_template_function<C, T>, Base, C> : Base
        {
            void templateFunction(typename as_param<Base, const T&>::type arg)
            { call(has_template_function<C, T>(), *this, arg); }
        };
    }
}

int main()
{
    any<has_template_function<_self, int>, _self&> c = Foo();
    c.templateFunction(5);

    //Compile error: cannot convert parameter 1 from 'const char [6]' to 'const int &'
    //c.templateFunction("Hello");

    return 0;
}
4

1 回答 1

2

这可以通过重载来实现,并记录在官方Boost.TypeErasure 文档中。

正如评论中所说,需要注意的是:

您不能键入擦除模板并保持其多态性

因此,您必须在 boost::typeerasure::any 类型的要求中明确指定重载。

您需要按照文档中的说明修改您的概念界面,并将字符串重载添加到需求部分。

您的示例,修改为处理重载:

#include <iostream>

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/member.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/any.hpp>
#include <string>
#include <utility>

using namespace std;
namespace mpl = boost::mpl;
using namespace boost::type_erasure;

struct FooStruct
{
    template <class T>
    void templateFunction(T t)
    {
        cout << t << endl;
    }
};

template<class T, class U>
struct has_template_function
{
    static void apply(T& t, const U& u) { t.templateFunction(u); }
};

namespace boost {
    namespace type_erasure {

        template<class T, class U, class Base, class Enable>
        struct concept_interface< ::has_template_function<T, U>, Base, T, Enable> : Base
        {
            typedef void _fun_defined;
            void templateFunction(typename as_param<Base, const U&>::type arg)
            {
                call(::has_template_function<T, U>(), *this, arg);
            }
        };

        template<class T, class U, class Base>
        struct concept_interface< ::has_template_function<T, U>, Base, T, typename Base::_fun_defined> : Base
        {
            using Base::templateFunction;
            void templateFunction(typename as_param<Base, const U&>::type arg)
            {
                call(::has_template_function<T, U>(), *this, arg);
            }
        };

    }
}

ostream& operator<<(ostream& os, const std::pair<int, string>& pair) {
    os << "(" << pair.first << ", " << pair.second << ")";
    return os;
}

int main()
{
    any<
        mpl::vector
        <
        has_template_function<_self, int>,
        has_template_function<_self, std::string>,
        has_template_function<_self, std::pair<int,std::string>>
        >
    , _self&> c = FooStruct();

    c.templateFunction(5);

    c.templateFunction("Hello");

    c.templateFunction(std::make_pair(5, "Hello"));

    return 0;
}
于 2013-09-06T12:55:46.887 回答