C++ ';模板参数推导/替换失败';加上一个论据之后
我需要一个模板函数,它将调用其他函数,参数取自C++ ';模板参数推导/替换失败';加上一个论据之后,c++,templates,c++11,template-argument-deduction,C++,Templates,C++11,Template Argument Deduction,我需要一个模板函数,它将调用其他函数,参数取自std::tuple。 我编写了一些代码,可以正确编译: #include <tuple> template<typename ...ARGS1, typename ...ARGS2> void foo(const std::tuple<ARGS1...> &, const std::tuple<ARGS2...> &) { //call function } int mai
std::tuple
。
我编写了一些代码,可以正确编译:
#include <tuple>
template<typename ...ARGS1, typename ...ARGS2>
void foo(const std::tuple<ARGS1...> &, const std::tuple<ARGS2...> &)
{
//call function
}
int main()
{
std::tuple<int, bool> tuple1(0, false);
std::tuple<double, void*, float> tuple2(0.0, nullptr, 0.0f);
foo(tuple1, tuple2);
return 0;
}
#包括
模板
void foo(常量std::tuple&,常量std::tuple&)
{
//调用函数
}
int main()
{
std::tupletuple1(0,false);
std::tupletuple2(0.0,nullptr,0.0f);
foo(tuple1,tuple2);
返回0;
}
现在我需要再添加一个参数,它是指向函数的指针:
#include <tuple>
template<typename ...ARGS1, typename ...ARGS2>
void foo(const std::tuple<ARGS1...> &, const std::tuple<ARGS2...> &, void (*)(ARGS1..., ARGS2...))
{
//call function
}
void bar(int, bool, double, void*, float)
{
}
int main()
{
std::tuple<int, bool> tuple1(0, false);
std::tuple<double, void*, float> tuple2(0.0, nullptr, 0.0f);
foo(tuple1, tuple2, &bar);
return 0;
}
#包括
模板
void foo(常量std::tuple&,常量std::tuple&,void(*)(ARGS1…,ARGS2…)
{
//调用函数
}
空栏(整数、布尔、双精度、空*、浮点数)
{
}
int main()
{
std::tupletuple1(0,false);
std::tupletuple2(0.0,nullptr,0.0f);
foo(tuple1、tuple2和bar);
返回0;
}
我尝试了许多不同的方法,但编译器总是返回模板参数推断/替换失败
和参数包推断与“”和“”
不一致。我不明白,我的代码怎么了。编译器输出中没有任何有用的信息
有人能帮我把这个写好吗?我的问题有一个很好的答案,它消失了。我不知道为什么 这不是我的想法,但我不记得作者了
template<typename ...ARGS1, typename ...ARGS2, typename ...ARGS3>
void foo(const std::tuple<ARGS1...> &, const std::tuple<ARGS2...> &, void (*)(ARGS3...))
{
//call function
}
模板
void foo(常量std::tuple&,常量std::tuple&,void(*)(ARGS3…)
{
//调用函数
}
我的问题有一个很好的答案,它消失了。我不知道为什么
这不是我的想法,但我不记得作者了
template<typename ...ARGS1, typename ...ARGS2, typename ...ARGS3>
void foo(const std::tuple<ARGS1...> &, const std::tuple<ARGS2...> &, void (*)(ARGS3...))
{
//call function
}
模板
void foo(常量std::tuple&,常量std::tuple&,void(*)(ARGS3…)
{
//调用函数
}
由于在本例中,clang++显示了一种不同(而且奇怪)的行为,所以我不能完全确定这个答案。但是,我想我可以解释使用g++时发生了什么
让我们看一下以下示例:
#include <iostream>
template<typename ...ARGS1, typename ...ARGS2>
void foo(void (*)(ARGS1..., ARGS2...))
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
void bar(int, bool, double, void*, float) {}
int main() {
foo(&bar);
}
正如我们所看到的,g++没有为ARGS1
推导任何东西,而是为ARGS2
推导了bar
的所有类型的函数参数
模板参数推导分别适用于每个函数参数。如果模板参数
T
是从两个函数参数推导出来的,则推导出的类型必须相同(只有少数例外)。同样,对于参数包。考虑:
template<typename T>
void foo(T, T) {}
foo(1, 2.3)
第一个和第二个功能参数的T.
推导结果不一致。这种不一致会导致编译错误
正如我们在回答的第一部分所看到的,对于如下参数:
template<typename ...ARGS1, typename ...ARGS2>
void foo(void (*)(ARGS1..., ARGS2...))
然后,ARGS2
的扣除结果必须一致:
void bar(int, double);
tuple<int, double> t;
foo(&bar, t); // works
tuple<double> u;
foo(&bar, u) // fails: inconsistent deduction results.
对于像some\u class\u template::nested\u type
这样的参数,T
处于非推断上下文中。这在上面的例子中使用,尽管有一些语法上的修饰
通常在C++中传递函数到另一个函数的方式是不同的,虽然:
template<typename F>
void foo(F f)
{
//call function, e.g.
f(42);
}
模板
无效foo(F)
{
//调用函数,例如。
f(42);
}
这允许传递任意函数对象,包括指向函数的指针。因为在这种情况下,clang++表现出不同(而且奇怪)的行为,所以我不能完全确定这个答案。但是,我想我可以解释使用g++时发生了什么 让我们看一下以下示例:
#include <iostream>
template<typename ...ARGS1, typename ...ARGS2>
void foo(void (*)(ARGS1..., ARGS2...))
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
void bar(int, bool, double, void*, float) {}
int main() {
foo(&bar);
}
正如我们所看到的,g++没有为ARGS1
推导任何东西,而是为ARGS2
推导了bar
的所有类型的函数参数
模板参数推导分别适用于每个函数参数。如果模板参数
T
是从两个函数参数推导出来的,则推导出的类型必须相同(只有少数例外)。同样,对于参数包。考虑:
template<typename T>
void foo(T, T) {}
foo(1, 2.3)
第一个和第二个功能参数的T.
推导结果不一致。这种不一致会导致编译错误
正如我们在回答的第一部分所看到的,对于如下参数:
template<typename ...ARGS1, typename ...ARGS2>
void foo(void (*)(ARGS1..., ARGS2...))
然后,ARGS2
的扣除结果必须一致:
void bar(int, double);
tuple<int, double> t;
foo(&bar, t); // works
tuple<double> u;
foo(&bar, u) // fails: inconsistent deduction results.
对于像some\u class\u template::nested\u type
这样的参数,T
处于非推断上下文中。这在上面的例子中使用,尽管有一些语法上的修饰
通常在C++中传递函数到另一个函数的方式是不同的,虽然:
template<typename F>
void foo(F f)
{
//call function, e.g.
f(42);
}
模板
无效foo(F)
{
//调用函数,例如。
f(42);
}
这允许传递任意函数对象,包括指向函数的指针。为什么不让函数完全通用?这个问题将消失,除了函数指针之外,您还可以使用函子和lambda
template void foo(…,F func){}
编译器试图从函数模板的第一个和第三个参数推断出ARGS1
,并得到不同的结果。您可以告诉它不要尝试从第三个参数推断参数包,例如,通过template struct identity\u t{using type=t;};使用非上下文=typename identity\u t::type的模板
,然后是一个类型为非推断上下文的参数,但这只是一个解决办法。这对我来说很好(铿锵svn trunk)。@Columbo Hmmm.[temp.decreate.type]/5.7说“函数参数包不会出现在参数声明列表的末尾。”是一个非推断上下文,用于从类型推断模板参数。因此,ARGS1
应该在第三个参数的非推断上下文中,但是ARGS2
不应该。如果为第三个参数推导了ARGS2
,则推导结果应该与第二个参数的推导结果不同,因此我们得到的结果不一致,并且推导失败。@Columbo由于模板参数推导对每个函数模板的函数参数都独立工作,因此没有