Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 涉及非推断参数包的函数指针参数类型的模板参数推断_C++_C++11_Language Lawyer_Variadic Templates_Template Argument Deduction - Fatal编程技术网

C++ 涉及非推断参数包的函数指针参数类型的模板参数推断

C++ 涉及非推断参数包的函数指针参数类型的模板参数推断,c++,c++11,language-lawyer,variadic-templates,template-argument-deduction,C++,C++11,Language Lawyer,Variadic Templates,Template Argument Deduction,这类似于,但更为具体。这一次,没有编译器按预期工作 template<class T> struct nondeduced { using type = T; }; template<class T> using nondeduced_t = typename nondeduced<T>::type; template<class... T, class U> void f(void(*)(nondeduced_t<T>..

这类似于,但更为具体。这一次,没有编译器按预期工作

template<class T>
struct nondeduced
{
    using type = T;
};

template<class T>
using nondeduced_t = typename nondeduced<T>::type;

template<class... T, class U>
void f(void(*)(nondeduced_t<T>..., U)) {}

void g(int, char) { }

int main()
{
    f<int>(g); // error?
}
因为参数pack
T
已经根据

非推断上下文为:

  • 不在参数声明列表末尾出现的函数参数包
不幸的是,我测试的编译器(g++/clang)都不接受该代码。 值得注意的是,下面这样的东西在g++和clang上都有效

template<class... T>
void f(void(*)(nondeduced_t<T>..., char)) {}
模板
void f(void(*)(非派生的,字符)){}
同样,这两种方法都不起作用:

template<class... T>
void f(void(*)(T..., char)) {}
模板
void f(void(*)(T…,char)){
我的期望是错误的吗?

由一个未推断的上下文引起

不在参数声明列表末尾出现的函数参数包

不作为模板函数的最后一个参数出现的参数包永远不会被推断,但完全可以指定禁用推断的参数类型。e、 g

template<class T1, class ... Types> void g1(Types ..., T1);

g1<int, int, int>(1,2,3);  // works by non-deduction
g1(1,2,3)                  // violate the rule above by non-deduced context
模板无效g1(类型…,T1);
g1(1,2,3);//非扣除作品
g1(1,2,3)//通过非推断上下文违反上述规则
但改变函数参数的顺序,即使保留模板参数不变,也会去除未推导的上下文条件,打破参数包的无限扩展。e、 g

template<class T1, class ... Types> void g1(T1, Types ...);
g1(1,2,3)                 // works because its a deduced context.
模板无效g1(T1,类型;
g1(1,2,3)//之所以有效,是因为它是一个推导出的上下文。
代码无法编译有两个原因:

  • 函数参数的顺序创建了一个未推导的上下文,这导致永远无法推导函数f中所述模式中的参数包T的类型

  • 模板参数T仅作为限定符出现在函数参数中(例如非派生参数),而不是直接指定为函数参数(允许参数推断)

  • 要使代码编译,您可以放置参数包的扩展,因为它忘记了非派生的\u t间接,如

    template<class... T,class U>
    void f( void(*)(U,T...) ) { }
    
    f(g);
    
    模板
    无效f(无效(*)(U,T…){}
    f(g);
    
    或者更改模板参数的顺序,并在函数调用时指定模板参数,如下所示

    template<class U,class... T>
    void f( void(*)(U,typename nondeduced<T>::type...) ) {}
    
    f<int,char>(g);    
    
    模板
    void f(void(*)(U,typename非派生::type…){}
    f(g);
    
    有人请在这里帮我学习一下。我本以为
    模板void f(void(*)(非导出的,U)){
    格式不正确,因为首先出现的是可变参数包。@CPPFREFERENCE中的AndyG:这似乎不是由SPECCCI明确指定的。请相信
    T.
    在标准下应该是贪婪的-它不应该为
    U
    消费留下任何东西,因此没有歧义。是吗?这是正常的吗?它们在问题中是非故意推断的。您不能通过更改前提条件来回答问题。
    template<class U,class... T>
    void f( void(*)(U,typename nondeduced<T>::type...) ) {}
    
    f<int,char>(g);