使用MSVC12时,我尝试typedef
依赖类型名称时会出现奇怪的语法错误:
template <typename ... LeftT>
struct A{
template <typename ...>
struct B{};
template <typename T, typename ... RightT>
struct B <T, RightT ... >{
typedef typename A<LeftT ..., T> nextA;
typedef typename nextA::B<RightT ...> nextB; //error C2059: syntax error : '<'
};
};
这就是它的一切,模板永远不会被实例化,除了内部。
我的问题:为什么我在这里遇到语法错误?这是无效的语法吗?
你质疑(可能):你为什么要这样做?
基本思想是通过类型转换进行转发。这可以通过专门化B
来完成,以便T
具有某种类型,然后可以转换。下面将详细介绍其工作原理,包括完整的代码段。
如果这个问题措辞严厉或难以理解,请帮助我改进。这是我一直在研究英语的最复杂的模板问题之一,不是我的母语。
作为一个练习,我想编写一个模板构造,允许我调用printf
以及需要char[]
和std::string
s的类似函数。
为此,我必须遍历每一个参数,并专注于它可能是std::string
的情况。为了做到这一点,我有一个结构fwd<typename func_t, typename ... LeftArgs>
,它包含已处理的所有参数,并在结构one_arg<typename Arg, typename ... RightArgs>
内,允许通过专用于空基数来处理当前参数案例和Arg
为std::string
的案例。基本情况(没有参数,或者没有剩下要处理),如下处理:
template<typename ...>
struct one_arg
{
//implementation of return_type will be shown below
static return_type forward(func_t func, LeftArgs ... leftArgs){
return func(leftArgs ...); //execute function
}
};
基础案例的专业化是一个常见的情况,即参数除std::string
以外的任何类型:
template<typename Arg, typename ... RightArgs>
struct one_arg < Arg, RightArgs ...>
{
//move Arg to the processed arguments
typedef typename fwd< func_t, LeftArgs..., Arg>::one_arg<RightArgs...> next_arg;
static return_type forward(func_t func, LeftArgs ... leftArgs, Arg arg, RightArgs ... rightArgs){
return next_arg::forward(func, leftArgs ..., arg, rightArgs ...);
}
};
使用几乎相同的语法进一步专门研究这种常见情况,当前参数的确属于std::string
类型:
template<typename ... RightArgs>
struct one_arg < std::string, RightArgs ...>
{
//again, move Arg to the processed arguments, but as a char[]
typedef typename fwd< func_t, LeftArgs..., char[]>::one_arg<RightArgs...> next_arg;
static return_type forward(func_t func, LeftArgs ... leftArgs, std::string arg, RightArgs ... rightArgs){
//convert string to char[]
return next_arg::forward(func, leftArgs ..., arg.c_str(), rightArgs ...);
}
};
我希望结构很明显。如果没有,这是完整的片段,准备好了。
#include <string>
using namespace std;
//get the return type of a function
template <typename T>
struct get_return_type;
template <typename R, typename ... A>
struct get_return_type<R(A...,...)>
{
typedef R type;
};
template<typename func_t, typename ... LeftArgs>
struct fwd{
typedef typename get_return_type<func_t> return_type;
//empty base case
template<typename ...>
struct one_arg
{
static return_type forward(func_t func, LeftArgs ... leftArgs){
return func(leftArgs ...);
}
};
//normal forwarding
template<typename Arg, typename ... RightArgs>
struct one_arg < Arg, RightArgs ...>
{
typedef typename fwd< func_t, LeftArgs..., Arg>::one_arg<RightArgs...> next_arg;
static get_return_type<func_t> forward(func_t func, LeftArgs ... leftArgs, Arg arg, RightArgs ... rightArgs){
return next_arg::forward(func, leftArgs ..., arg, rightArgs ...);
}
};
//specialisation for std::string
template<typename ... RightArgs>
struct one_arg < std::string, RightArgs ...>
{
typedef typename fwd< func_t, LeftArgs..., char[]>::one_arg<RightArgs...> next_arg;
static get_return_type<func_t> forward(func_t func, LeftArgs ... leftArgs, std::string arg, RightArgs ... rightArgs){
return next_arg::forward(func, leftArgs ..., arg.c_str(), rightArgs ...);
}
};
};
template<typename func_t, typename ... Args>
typename fwd<func_t>::one_arg<Args ...>::return_type forward_stoc(func_t func, Args ... args){
typedef typename fwd<func_t>::one_arg<Args ...> next_arg;
return next_arg::forward(func, args...);
}
答案 0 :(得分:2)
nextA
是一个依赖范围,因此您需要指明B
是模板的名称:
typedef typename nextA::template B<RightT ...> nextB;
^^^^^^^^
请注意,typename
的声明中不应该有nextA
,因为没有涉及的依赖范围:
typedef A<LeftT ..., T> nextA;
有关血腥的详细信息,请参阅Where and why do I have to put the "template" and "typename" keywords?