【发布时间】:2016-07-05 19:00:36
【问题描述】:
我有几个范围的boost::variant。在这种情况下,range 只是一个std::pair<It, It>,其中It 是一个迭代器。我用它来存储满足某些属性的迭代器范围。
由于我不知道迭代器的类型,我使用了一点模板元编程来获取std::pair 的first_type,因为我需要第二个包含单个迭代器的boost::variant(对应于一些active 该类型的元素)。
以下代码已简化以帮助解决该问题,但请考虑我的RangeVariant 中有未知数量的范围(这意味着我无法手动创建它,因为我可以针对这种特殊情况执行此操作)。
#include <utility>
#include <vector>
#include <boost/variant.hpp>
template <class A, template <typename...> class B>
struct FirstTypeVariantImpl;
template <template <typename...> class A, typename... Pair, template <typename...> class B>
struct FirstTypeVariantImpl<A<Pair...>, B> /*! specialization */
{
using type = B<typename Pair::first_type...>;
};
template <class A, template <typename...> class B>
using FirstTypeVariant = typename FirstTypeVariantImpl<A, B>::type;
int main()
{
using Container = std::vector<int>;
using Range = std::pair<Container::iterator, Container::iterator>;
using RangeVariant = boost::variant<Range>;
using IteratorVariant = FirstTypeVariant<RangeVariant, boost::variant>;
};
上面的程序用 gcc 可以正确编译,但是用 clang 编译失败。我得到的错误如下:
program.cpp:12:29: error: incomplete type 'boost::detail::variant::void_' named in nested name specifier
using type = B<typename Pair::first_type...>;
^~~~~~
program.cpp:16:1: note: in instantiation of template class 'FirstTypeVariantImpl<boost::variant<std::pair<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > >, boost::detail::variant::void_, ..., boost::detail::variant::void_>, variant>' requested here
using FirstTypeVariant = typename FirstTypeVariantImpl<A, B>::type;
^
program.cpp:23:29: note: in instantiation of template type alias 'FirstTypeVariant' requested here
using IteratorVariant = FirstTypeVariant<RangeVariant, boost::variant>;
^
../../../include/boost/variant/variant_fwd.hpp:193:8: note: forward declaration of 'boost::detail::variant::void_'
struct void_;
^
所以,clang 似乎试图获取boost::detail::variant::void_ 的first_type,但不知何故 gcc 识别它并忽略它。如果我使用 <tuple> 标头获取第一个元素的类型,则会发生类似的情况:
using type = B<typename std::tuple_element<0, Pair>::type...>;
此更改后的错误不同,但又与 clang 尝试将操作应用于boost::detail::variant::void_:
program.cpp:13:34: error: implicit instantiation of undefined template 'std::tuple_element<0, boost::detail::variant::void_>'
using type = B<typename std::tuple_element<0, Pair>::type...>;
我正在使用 boost 1.57.0、gcc 4.8.3 和 clang 3.6.0,始终使用带有 -Wall -Werror -Wextra 标志的 -std=c++11。不能使用其中任何一个的其他版本:-(
任何帮助将不胜感激。如果我的用法不正确,我什至不知道这是否是 clang 或 boost 中的错误,甚至是 gcc 中的错误。提前感谢您的帮助。
【问题讨论】:
-
你说 g++ 编译你的代码很奇怪。我在 g++ 和 clang 上都有相同的编译错误。
-
你使用的是同一个版本的gcc吗?我的是 4.8.3。
-
4.8.2 和 5.3.0 - 两者都编译错误。
-
嗯,不完全一样。也许有一些相关的差异。 boost的版本呢?我的是 1.57.0。只是出于好奇:您使用 GCC 4.8.2 得到的编译错误究竟是什么?
标签: c++ clang metaprogramming template-meta-programming boost-variant