3

我需要 std::pair.first 的惰性评估版本。我的方法是使用 boost::phoenix,定义一个模板函数并使用 BOOST_PHOENIX_ADAPT_FUNCTION makro,如下所示:

template <typename T1, typename T2>
T1 first_impl(std::pair<T1,T2> p){
    return p.first;
}
BOOST_PHOENIX_ADAPT_FUNCTION(std::string, first, first_impl, 1);

对于我当前程序中需要的特定情况很好(在我的情况下 T1 = std::string)。但是如何使用 first_impl 函数模板的结果类型 T1 来进一步抽象它以供将来使用?文档提到了使用typename remove_reference<A0>::type作为 makro 的第一个参数来将函数的返回类型定义为其第一个参数的类型。基于此,我尝试了几个版本,例如:

BOOST_PHOENIX_ADAPT_FUNCTION(typename A0::first_type, first, first_impl, 1); 

试图访问std::pair<T1, T2>::first_type这似乎对我不起作用。

另外,我尝试调整std::remove_reference处理此问题的方法,如下所示

template <typename T1, typename T2> first_type < std::pair<T1,T2> > 
{ typedef T1 type; }

但这似乎也不起作用。有人可以指出我在这里做错了什么吗?

4

1 回答 1

3

我建议一个特征,确实就像你几乎拥有的那样first_type

namespace detail // by convention, hide details from enclosing namespace
{
    template <typename Pair, typename First = typename std::remove_reference<Pair>::type::first_type> 
    struct first_type {
        typedef First type;
    };

// Now you can use the trait in your `first_impl` return type:

    template <typename Pair>
    typename first_type<Pair>::type first_impl(Pair const& p){
        return p.first;
    }
}

现在,您确实可以在改编中使用:

BOOST_PHOENIX_ADAPT_FUNCTION(typename detail::first_type<A0>::type, first, detail::first_impl, 1)

完整的演示:在 Coliru 上实时观看

int main()
{
    using boost::phoenix::arg_names::arg1;

    std::map<std::string, int> const m { 
        { "one",   1 },
        { "two",   2 },
        { "three", 3 },
        { "four",  4 }
    };

    std::for_each(begin(m), end(m), std::cout << first(arg1) << "\n");
}

输出

four
one
three
two
于 2013-10-15T19:58:00.143 回答