c++ - 使用可变参数模板时出现意外的隐式转换?

标签 c++ c++11 casting variadic-templates implicit-conversion

给定这段代码:

#include <iostream>

template<typename... Args> class X;

template<typename T>
class X<T> {
 public:
    T value;
    X(T value_) : value(value_) {}
};

template<typename T, typename... Args>
class X<T, Args...> : public X<Args...> {
 public:
    T value;
    X(T value_, Args... args) : value(value_), X<Args...>(args...) {}
};

template<typename T>
std::ostream& operator <<(std::ostream& stream, const X<T>& value_) {
    stream << value_.value;
    return stream;
}

template<typename T, typename... Args>
std::ostream& operator <<(std::ostream& stream, const X<T, Args...>& value_) {
    stream << value_.value << " " << static_cast<X<Args...> const& >(value_);
    return stream;
}

class Person : public X<std::string, int>{
 public:
    Person(std::string name, int age) : X<std::string, int>(name, age) {}
};


int main()
{
   std::cout << Person("Me", 35) << std::endl;
   return 0;
}

使用 'g++ -std=c++11 main.cpp' 使用 gcc 4.7.2 编译,执行时给出以下输出:

35

我期待它打印:

Me 35

因为它应该首先匹配 Person 的直接父类(super class)而不是其超父类(super class)的运算符<<,对吗?但这似乎并没有发生。它只打印了作为 X 行为的 int,而不是作为直接父类(super class) X 行为的两个项目。这是预期的吗?

最佳答案

解决您的问题:

#include <iostream>

template<typename... Args> class X;

template<typename T>
class X<T> {
 public:
    T value;
    explicit X(T value_) : value(value_) {}
};

template<typename T, typename... Args>
class X<T, Args...> : public X<Args...> {
 public:
    T value;
    explicit X(T value_, Args... args) : X<Args...>(args...), value(value_) {}
};

这种类型让我们可以使用标签分派(dispatch)来根据 X 的参数数量选择重载。 :

template<std::size_t> struct compile_time_size {};

这里有 3 个重载。 0 个参数的第一个错误,第二个句柄 1,第三个句柄 N :

template<typename... Ts>
std::ostream& output_helper(std::ostream&, const X<Ts...>&, compile_time_size<0>) = delete;

template<typename T, typename... Ts>
std::ostream& output_helper(std::ostream& stream, const X<T, Ts...>& value, compile_time_size<1>)
{
    stream << value.value;
    return stream;
}
template<typename T, typename... Ts, std::size_t N>
std::ostream& output_helper(std::ostream& stream, const X<T, Ts...>& value, compile_time_size<N>)
{
    stream << value.value << " " << static_cast< X<Ts...> const& >(value);
    return stream;
}

我们的 <<现在只是一个重载,这使得推理变得容易。然后它分派(dispatch)给上面的辅助函数,显式传递长度。他们重新发送回 <<使用 ADL 查找在自己之后声明的函数:

template<typename... Ts>
std::ostream& operator<<(std::ostream& stream, const X<Ts...>& value) {
    return output_helper( stream, value, compile_time_size<sizeof...(Ts)>() );
}

live example

关于c++ - 使用可变参数模板时出现意外的隐式转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21963658/

相关文章:

c++ - 为什么我的代码无法处理大数组输入(>10000)?

c++ - 使用内嵌 asm 编写一个带有 2 个比较的 for 循环

date - 从带破折号的字符串解析 Pandas 列到日期

scala - 这个流的类型是如何转换的?

c++ - 将一个 long double 存储在多个 double 变量中

python - 从 c++ 中的 python 程序中检索 stderr

(s)printf 的 C++ 标准替代品

c++ - 将 shared_ptr 与自定义相等运算符和 STL 结合使用时出现问题

c++ - 什么是非 POD 对象的 xvalue 和 prvalue 之间允许的使用或行为差异的示例?

c++ - 在 C++ 中创建 lambda 映射