给定这段代码:
#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
最佳答案
解决您的问题:
#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)>() );
}
关于c++ - 使用可变参数模板时出现意外的隐式转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21963658/