decltype和boost :: variant - 检索当前值

时间:2014-02-10 20:53:25

标签: c++ boost c++11 boost-variant

我有以下代码:

#include <boost/variant.hpp>

#include <iostream>
#include <string>

boost::variant<int, double, std::string> variant;

template <typename FirstArg, typename... OtherArgs>
auto bar(const std::type_info& variant_type_info) -> decltype(typeid(FirstArg) == variant_type_info ? boost::get<FirstArg>(variant) : bar<OtherArgs...>(variant_type_info))
{
    if (typeid(FirstArg) == variant_type_info)
    {
        return boost::get<FirstArg>(variant);
    }

    return bar<OtherArgs...>(variant_type_info);
}

template <typename... VariantArgs>
auto foo(const boost::variant<VariantArgs...>& variant) -> decltype(bar<VariantArgs...>(variant.type()))
{
    return bar<VariantArgs...>(variant.type());
}

int main()
{
    variant = 0.5;
    const auto& baz = foo(variant);
    std::cout << baz << '\n';
}

它给了我以下错误:

main.cpp:9:135: error: 'bar' was not declared in this scope

 auto bar(const std::type_info& variant_type_info) -> decltype(typeid(FirstArg) == variant_type_info ? boost::get<FirstArg>(variant) : bar<OtherArgs...>(variant_type_info))

                                                                                                                                       ^

main.cpp:9:148: error: expected primary-expression before '...' token

 auto bar(const std::type_info& variant_type_info) -> decltype(typeid(FirstArg) == variant_type_info ? boost::get<FirstArg>(variant) : bar<OtherArgs...>(variant_type_info))

                                                                                                                                                    ^

main.cpp:9:148: error: expected ')' before '...' token

main.cpp:9:135: error: 'bar' was not declared in this scope

 auto bar(const std::type_info& variant_type_info) -> decltype(typeid(FirstArg) == variant_type_info ? boost::get<FirstArg>(variant) : bar<OtherArgs...>(variant_type_info))

                                                                                                                                       ^

main.cpp:9:54: error: expected type-specifier before 'decltype'

 auto bar(const std::type_info& variant_type_info) -> decltype(typeid(FirstArg) == variant_type_info ? boost::get<FirstArg>(variant) : bar<OtherArgs...>(variant_type_info))

                                                      ^

main.cpp:9:54: error: expected initializer before 'decltype'

main.cpp:20:69: error: 'bar' was not declared in this scope

 auto foo(const boost::variant<VariantArgs...>& variant) -> decltype(bar<VariantArgs...>(variant.type()))

                                                                     ^

main.cpp:20:69: error: 'bar' was not declared in this scope

main.cpp:20:84: error: expected primary-expression before '...' token

 auto foo(const boost::variant<VariantArgs...>& variant) -> decltype(bar<VariantArgs...>(variant.type()))

                                                                                    ^

main.cpp:20:84: error: expected ')' before '...' token

main.cpp:20:69: error: 'bar' was not declared in this scope

 auto foo(const boost::variant<VariantArgs...>& variant) -> decltype(bar<VariantArgs...>(variant.type()))

                                                                     ^

main.cpp:20:69: error: 'bar' was not declared in this scope

main.cpp:20:60: error: expected type-specifier before 'decltype'

 auto foo(const boost::variant<VariantArgs...>& variant) -> decltype(bar<VariantArgs...>(variant.type()))

                                                            ^

main.cpp:20:60: error: expected initializer before 'decltype'

main.cpp: In function 'int main()':

main.cpp:28:34: error: 'foo' was not declared in this scope

     const auto& baz = foo(variant);

Coliru示例 - http://coliru.stacked-crooked.com/a/4467c33489b08359

我看到我无法在decltype中引用相同的函数。这种情况有没有解决办法?我正在尝试编写函数来从boost :: variant对象中检索当前值。

1 个答案:

答案 0 :(得分:3)

是的,一般情况下有解决方法。它被称为:

部分订购。要获得引用,请将方法移动到类命名空间中。

<强>然而

没有什么可以救你的。除非你在编译时已经知道它,否则你无法让编译器恢复参数的静态类型。这应该是显而易见的。

我的意思是,foo()的返回类型应该是什么?它怎么可能包含所有可能的元素类型?对。这就是你开始使用变体的原因。

前进的三种方式:

  1. 静态了解类型:

    const auto& baz = boost::get<double>(variant); 
    
  2. 返回typeid:

    std::type_info const& typeinfo_value = variant.type();
    
  3. 分支并创建单独的路径来处理所有情况。对于这种情况,Boost有static_visitor:

    struct Visitor : boost::static_visitor<std::string> {
        std::string operator()(std::string const&) const { return "std::string"; }
        std::string operator()(int) const { return "int"; }
        std::string operator()(double) const { return "double"; }
    
        template <typename... T>
            std::string operator()(boost::variant<T...> const& v) const {
                return boost::apply_visitor(*this, v);
             }
    };
    
    int main()
    {
        static const Visitor _visitor;
    
        variant = 0.5f;
        std::cout << "The actual type is " << _visitor(variant) << "\n";
    }