使用boost-mpl进行C++编译时字符串连接

5
我正在尝试使用boost-mpl在编译时连接字符串,但是收到了来自gcc的错误。这是样例代码 -
using namespace boost;
using namespace std;

template<class A>
struct type {};

template<>
struct type<int> {
    typedef mpl::string < 'i' > value;
};

template<>
struct type<char> {
    typedef mpl::string < 'c' > value;
};

struct empty {
};

template<class A, class B, class C, class D>
struct converter;

template<class A, class B = empty, class C = empty, class D = empty>

struct converter {
    typedef mpl::push_back< type<A>::value, converter<B,C,D>::value >::type value ;
};

template<>
struct converter<empty, empty, empty, empty> {
    typedef mpl::string < '\0' > value;
};

所以,我想要实现的是:
converter<int,char,int> == "ici\0" // true. 

问题是在gcc中,上述代码会报以下错误:
main.cpp:37: error: type/value mismatch at argument 1 in template parameter list for ‘template<class Sequence, class T> struct boost::mpl::push_back’
main.cpp:37: error:   expected a type, got ‘type::value’
main.cpp:37: error: type/value mismatch at argument 2 in template parameter list for ‘template<class Sequence, class T> struct boost::mpl::push_back’
main.cpp:37: error:   expected a type, got ‘converter::value’

有人能指出上述代码的问题并解释正确的做法吗?谢谢。

编辑1:更正了格式和几个错别字。

编辑2: 在Lambdageek和Andy的建议之后,代码确实可以编译,但是当我尝试打印结果时……

int main(int argc, char** argv) {
    cout << mpl::c_str< converter<int,char>::value >::value << endl;
    return 0;
}

编译器报错 -

/usr/local/include/boost/mpl/string.hpp:534:   instantiated from ‘boost::mpl::c_str<boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> > > >’
main.cpp:49:   instantiated from here

/usr/local/include/boost/mpl/string.hpp:228: error: ‘value’ is not a member of ‘boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> >’

/usr/local/include/boost/mpl/string.hpp: In instantiation of ‘boost::mpl::c_str<boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> > > >’:
main.cpp:49:   instantiated from here
/usr/local/include/boost/mpl/string.hpp:548: error: no type named ‘value_type’ in struct boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> > >’
main.cpp: In function ‘int main(int, char**)’:
main.cpp:49: error: ‘value’ is not a member of ‘boost::mpl::c_str<boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::push_back<boost::mpl::string<105, 0, 0, 0, 0, 0, 0, 0>, boost::mpl::string<0, 0, 0, 0, 0, 0, 0, 0> > > >’
make[2]: *** [build/Debug/GNU-Linux-x86/main.o] Error 1
make[1]: *** [.build-conf] Error 2

我承认我在模板编程方面很新,所以问题肯定是一些基础问题。感谢所有的帮助。

编辑3: 更改了转换器结构中的push_back行。

错误:

main.cpp:41: error: type ‘boost::mpl::push_back<typename type<A>::value, typename converter<B, C, D, empty>::value>’ is not derived from type ‘converter<A, B, C, D>’
main.cpp:41: error: expected ‘;’ before ‘value’
3个回答

4

好的,根据您的最终编辑,我看到这里有几个问题。

首先,您可以使用mpl::push_back将元素添加到序列中。现在您正在连接两个序列。我更改了type<>::value的类型为mpl::char_,然后更改了mpl::push_back参数的顺序(先是序列,然后是元素)。此外,在此代码中,您必须使用push_front而不是push_back。最后,我在push_front之后添加了一个::type,因为您必须在此处提取实际类型。以下是参考代码:

using namespace boost;
using namespace std;

template<class A>
struct type {};

template<>
struct type<int> {
    typedef mpl::char_ < 'i' > value;
};

template<>
struct type<char> {
    typedef mpl::char_ < 'c' > value;
};

struct empty {
};

template<class A, class B, class C, class D>
struct converter;


template<class A, class B = empty, class C = empty, class D = empty>
struct converter {
        typedef typename mpl::push_front< typename converter<B,C,D>::value, typename type<A>::value >::type value ;
};


template<>
struct converter<empty, empty, empty, empty> {
    typedef mpl::string < '\0' > value;
};

现在,这段代码按预期工作:
int
main (void)
{
        cout << mpl::c_str< converter<int,char>::value >::value << endl;
        return 0;
}

(打印出ic)。

可以,谢谢。但是我很好奇,是否有一种使用mpl::string而不是char_来完成相同操作的方法?此外,我已经点赞了,但无法将其标记为答案,因为原始问题已由lambdageek回答 - 对此感到抱歉。 - Code freak
@Code,你的问题的答案不会生成有效的代码 :) 无论如何,我会研究如何在所有地方使用mpl::string来完成它,也许可以使用mpl::front_inserter - Diego Sevilla
2
@代码:可以完成。类型必须是:typedef typename mpl::copy< typename converter<B,C,D>::value, mpl::back_inserter< typename type<A>::value > >::type value;。这将把 type<A>::value 中的所有字符添加到转换器字符串的末尾。 - Diego Sevilla
谢谢。看起来很复杂,但我会尝试的 :) - Code freak

2

在IT技术中,加上typename关键字有助于告诉编译器::value是一个类型吗?

struct converter {
    typedef mpl::push_back< typename type<A>::value, typename converter<B,C,D>::value > value ;
};

谢谢。请检查更新的问题。代码现在可以编译,但是当我添加打印结果的代码时,我再次遇到了错误。 - Code freak

2
你需要使用关键字typename
typedef mpl::push_back< typename type<A>::value, typename converter<B,C,D>>:value >::type value;

当访问一个使用你的模板参数实例化的模板的嵌套typedef时,你需要帮助C++决定嵌套名称是指方法/字段还是嵌套类型定义。如果你没有说明,C++会假设它是一个字段名。如果你使用typename,它将假定嵌套的东西是一个类型。


谢谢。您的建议起作用了,但是当我尝试打印值时出现了一个新错误,请检查问题的编辑。 - Code freak
尝试在 push_back 行中添加 ::type。请参考 Boost 文档 中的示例。 - Lambdageek
将该行更改为typedef mpl::push_back<typename type<A>::value, typename converter<B,C,D>::value>::type value; 但现在我得到了main.cpp:41: error: type ‘boost::mpl::push_back<typename type<A>::value, typename converter<B, C, D, empty>::value>’ is not derived from type ‘converter<A, B, C, D>’的错误。 - Code freak
4
@Code:你的键盘似乎有问题。每次打“you”都会出现一个“u”。而且大写的“I”键好像坏了。你可能需要换一个新的键盘。 - sbi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接