Pat*_*erg 5 c++ variadic-templates c++11
这应该是使用可变参数模板的常见情况,例如当树行走的子节点是可变参数模板参数时.我找到了许多相关的问题和答案,但要么它们是略有不同的东西,要么它们是相同的东西,我没有得到它.现在来问题了.我有一个像这样的非变量元组
template <class E, class T1, class T2, class T3, etc...>
struct X;
Run Code Online (Sandbox Code Playgroud)
我正在重载函数以具有专门的行为,这取决于这样的元组的第一个元素是指针类型或向量指针类型.这工作正常,但如果我将模板参数打包到单个可变参数模板参数中,则重载变得模糊不清.这是错误消息:
variadic.cpp:42:17: error: ambiguous overload for ‘operator<<’ in ‘std::cout << y’
variadic.cpp:42:17: note: candidates are:...
Run Code Online (Sandbox Code Playgroud)
编译器应该更喜欢X<vector<V*>*,T*...>在X<H*,T*...>当它试图匹配vector<double*>*的元组的第一个元素.
我可以使用enable_if消除歧义,并且事情再次起作用.但是,我想了解错误,如果可能的话,找到其他方法然后启用enable_if.这是代码:
#include <iostream>
#include <vector>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/utility/enable_if.hpp>
using namespace std;
template <typename ... T>
struct X;
template <>
struct X <>
{
};
template <typename H, typename ... T>
struct X<H*,T*...> : public X<T*...>
{
H* value;
X(H* value, T*... args)
: value(value), X<T*...>(args...)
{
}
};
template <typename H, typename ... T>
#ifdef DO_NOT_WANNA_SEE_THE_BUG
typename boost::enable_if<boost::is_fundamental<H>, std::ostream>::type&
operator<<(std::ostream& stream, X<H*,T*...> const & x)
#else
std::ostream& operator<<(std::ostream& stream, X<H*,T*...> const & x)
#endif
{
return stream << "specialized scalar pointer";
}
template <typename V, typename ... T>
std::ostream& operator<<(std::ostream& stream, X<vector<V*>*,T*...> const & x)
{
return stream << "specialized vector pointer";
}
int main()
{
double a,b;
vector<double *> v;
X<double*,double*> x (&a,&b);
X<vector<double*>*, double*> y (&v, &b);
cout << x << endl;
cout << y << endl; // this line is ambiguous according to gcc 4.6 and later
}
Run Code Online (Sandbox Code Playgroud)
小智 0
实质来自 WhozCraig 的评论:
当您在两个模板中删除 T* 时,程序将编译(带有警告 -Wreorder)并给出预期的输出。
operator<<(std::ostream& stream, X<H*,T...> const & x)
operator<<(std::ostream& stream, X<vector<V*>*, T...> const & x)
Run Code Online (Sandbox Code Playgroud)
在没有任何启发的情况下浏览[14]模板后,我认为存在编译器错误。
修改后的测试:
#include <iostream>
#include <vector>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/utility/enable_if.hpp>
using namespace std;
#define USE_VARIADIC_TEMPLATE 1
#define USE_AMBIGUOUS 1
template <typename ... T>
struct X;
template <>
struct X <>
{
};
template <typename H, typename ... T>
struct X<H*,T*...> : public X<T*...>
{
H* value;
X(H* value, T*... args)
: X<T*...>(args...), value(value)
{}
};
#if USE_VARIADIC_TEMPLATE
template <typename H, typename ... T>
#if USE_AMBIGUOUS
std::ostream& operator<<(std::ostream& stream, X<H*,T*...> const & x)
#else
std::ostream& operator<<(std::ostream& stream, X<H*,T...> const & x)
#endif
#else
template <typename H, typename T>
std::ostream& operator<<(std::ostream& stream, X<H*, T*> const & x)
#endif
{
return stream << "specialized scalar pointer";
}
#if USE_VARIADIC_TEMPLATE
template <typename V, typename ... T>
#if USE_AMBIGUOUS
std::ostream& operator<<(std::ostream& stream, X<vector<V*>*,T*...> const & x)
#else
std::ostream& operator<<(std::ostream& stream, X<vector<V*>*,T...> const & x)
#endif
#else
template <typename V, typename T>
std::ostream& operator<<(std::ostream& stream, X<vector<V*>*, T*> const & x)
#endif
{
return stream << "specialized vector pointer";
}
int main()
{
double a,b;
vector<double *> v;
X<double*,double*> x (&a,&b);
X<vector<double*>*, double*> y (&v, &b);
cout << x << endl;
cout << y << endl; // this line is ambiguous according to gcc 4.6 and later
}
Run Code Online (Sandbox Code Playgroud)
甚至还有这样的情况:
template <typename H, typename T>
std::ostream& operator<<(std::ostream& stream, X<H*, T*> const & x)
template <typename V, typename T>
std::ostream& operator<<(std::ostream& stream, X<vector<V*>*, T*> const & x)
Run Code Online (Sandbox Code Playgroud)
编译得很好。
编辑:如果可变参数模板只包含一个作为 T* 传递的 T,那么它应该是上面所示的简单情况。