变异模板提取

时间:2014-11-19 16:17:28

标签: c++ templates c++11 variadic-templates

我遇到了一些我无法理解的事情,也找不到适当的解决方法。我想要实现的目标看起来相对简单:我想比较一些数据。

描述的最佳方式是一行代码:

std::tuple<const char *, int, const char *, int> my_data =
    std::make_tuple("hello", 13, "world", 37);
// Now I want to compare my_data againt some known value.
assert(Test::entry(my_data, "hello", 13, "world", 37));

为了示例,我使用了一个元组。我的情况是,这些数据来自消息对象,并使用operator>>提取。但是,这与问题无关。

这是一个用于说明问题的极简主义代码。

#include <cstring>
using MyTuple = std::tuple<const char *, int, const char *, int>;

namespace Test
{

  // called when we are done                                                                                                                                                                 
  bool extract(MyTuple source)
  {
    return true;
  }

  template<typename T,
           typename ...Content>
  bool extract(MyTuple source, T data, Content... content)
  {
    if (std::is_same<const char *, T>::value)
      assert(0); // why ? :(                                                                                                                                                                 
    std::cout << "Generic: " << data << std::endl;
    return extract(source, content...);
  }

  template<typename ...Content>
  bool extract(MyTuple source, const char *str, Content... content)
  {
    std::cout << "Overloaded: " << str << std::endl;
    return extract(source, content...);
  }

  template<typename ...Content>
  bool entry(const std::tuple<const char *, int, const char *, int> &data,
             Content... content)
  {
    return extract(data, content...);
  }

};

我会在extract()函数中正常执行比较,但为了保持示例简单,我删除了它们。

我想要实现的是适当的调度。基于这个例子,我的理解是呼叫顺序应该是:

  1. const char *
  2. 重载
  3. 通用
  4. const char *
  5. 的重载
  6. 通用
  7. 但是,此测试程序的输出是:

    1. 重载:hello
    2. Generic:13
    3. Assertion failedstd::is_same测试会触发assert
    4. 我发现在泛型重载调用一次后不会调用const char *重载。

      我错过了什么?

      编辑:也不是说如果我在泛型函数之前定义const char *重载,这甚至都不会编译。

1 个答案:

答案 0 :(得分:3)

  

另请注意,如果我在泛型函数之前定义const char *重载,则甚至无法编译。

声明应该足够了:

template <typename... Content>
bool extract(MyTuple source, const char *str, Content... content); // <- here

template <typename T, typename... Content>
bool extract(MyTuple source, T data, Content... content)
{
    std::cout << "Generic: " << data << std::endl;
    return extract(source, content...);
}

template <typename... Content>
bool extract(MyTuple source, const char *str, Content... content)
{
    std::cout << "Overloaded: " << str << std::endl;
    return extract(source, content...);
}
  

为什么?

在没有事先声明的特定名称查找期间,过载const char*不可见。可以在comments below中找到一些例外情况。