当给定默认值时,为什么此模板参数推导失败
Why does this template argument deduction fail when a default value is given?
以下代码有效:
template <typename T>
struct Foo
{
template <typename OStream>
static void default_print_function(OStream &, const T &);
template <typename OStream, typename PrintFunction>
void print(
OStream &,
const PrintFunction & = &Foo<T>::default_print_function<OStream>) const;
template <typename OStream>
void print(OStream &) const;
};
template <typename T>
template <typename OStream>
void Foo<T>::default_print_function(OStream & o, const T & value)
{
o << value;
}
template <typename T>
template <typename OStream, typename PrintFunction>
void Foo<T>::print(OStream & o, const PrintFunction & f)
const
{
T test_value = 123;
o << "TEST: ";
f(o, test_value);
}
template <typename T>
template <typename OStream>
void Foo<T>::print(OStream & o)
const
{
print(o, &default_print_function <OStream>);
}
#include <iostream>
int main()
{
Foo <int> foo;
foo.print(std::cerr, &Foo<int>::default_print_function<std::ostream>);
std::cerr << std::endl;
foo.print(std::cerr);
std::cerr << std::endl;
}
但是,如果我注释掉void print (OStream &) const
过载:
template <typename T>
struct Foo
{
template <typename OStream>
static void default_print_function(OStream &, const T &);
template <typename OStream, typename PrintFunction>
void print(
OStream &,
const PrintFunction & = &Foo<T>::default_print_function<OStream>) const;
template <typename OStream>
void print(OStream &) const;
};
template <typename T>
template <typename OStream>
void Foo<T>::default_print_function(OStream & o, const T & value)
{
o << value;
}
template <typename T>
template <typename OStream, typename PrintFunction>
void Foo<T>::print(OStream & o, const PrintFunction & f)
const
{
T test_value = 123;
o << "TEST: ";
f(o, test_value);
}
/*template <typename T>
template <typename OStream>
void Foo<T>::print(OStream & o)
const
{
print(o, &default_print_function <OStream>);
}*/
#include <iostream>
int main()
{
Foo <int> foo;
foo.print(std::cerr, &Foo<int>::default_print_function<std::ostream>);
std::cerr << std::endl;
foo.print(std::cerr);
std::cerr << std::endl;
}
然后它就不会编译:
test.cpp: In function ‘int main()’:
test.cpp:54:25: error: no matching function for call to ‘Foo<int>::print(std::ostream&)’
foo .print (std :: cerr);
^
test.cpp:8:7: note: candidate: template<class OStream, class PrintFunction> void Foo<T>::print(OStream&, const PrintFunction&) const [with OStream = OStream; PrintFunction = PrintFunction; T = int]
void print (
^~~~~
test.cpp:8:7: note: template argument deduction/substitution failed:
test.cpp:54:25: note: couldn't deduce template parameter ‘PrintFunction’
foo .print (std :: cerr);
print
的第二个参数的默认值的拼写方式在我看来与main
函数的第一次调用中的拼写方式完全相同。
foo .print (std :: cerr, & Foo <int> :: default_print_function <std :: ostream>);
那么,为什么模板参数可以在这次调用中推导出来,而不能在默认参数中推导出来呢
const PrintFunction & = & Foo <T> :: default_print_function <OStream>
这是一个非推导上下文:
cppreference
非推导上下文:
4( 函数的参数类型中使用的模板参数具有在调用中使用的默认参数的参数正在对哪个自变量进行推导
编辑(为什么它是非推导上下文(
因为非推导上下文有一个好处:如果可以从其他地方获得该类型,则可以使用该类型。
考虑这个例子:
template<class T>
void foo(T, T = 1.0) {};
int main() {
foo(2);
}
这是有效的代码。但如果它不是一个非推导的上下文,推导就会发生冲突。假设程序员希望进行转换而不是失败,这在一定程度上是合理的。
另一方面,类型本质上是在其他地方给定的(在声明中给定的默认参数(。例如,如果您decltype
到模板参数,您的代码将是好的
template <typename OStream, typename PrintFunction = decltype(&Foo<T>::default_print_function<OStream>)>
总而言之,我们没有损失任何东西使它成为一个非推导的上下文。此外,当在其他地方提供默认参数类型时,我们可以转换该类型。
相关文章:
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 视图中的参数推导失败:take_while
- variadic模板中的模板参数推导失败
- 当给定默认值时,为什么此模板参数推导失败
- 模板参数推导失败,函数参数/参数不匹配
- 为什么模板参数推导失败?
- 嵌套参数包扩展失败
- 模板参数的 C++ 自动模板推导失败
- 调试模板时出现问题.专门针对 Linux GCC 7、GCC 6、GCC 5、GCC 4.9 错误构建失败:模板参数 1
- 使用显式模板参数列表和 [temp.arg.explicit]/3 的函数调用的演绎失败
- 失败,出现错误 87:参数不正确.如何判断哪个参数不正确?
- 在 g++ 6.2.1 中将参数包转发到 constructor() 失败
- 当变量和参数名称匹配时,移动语义构造失败
- 作为模板参数的成员函数指针在继承的成员函数上失败,如何以及为什么?
- 模板参数推导/替换失败,lambda作为函数指针
- 为什么在 std::transform 中使用函数对象参数失败并且需要 lambda 表达式
- C++模板参数失败,不是从错误派生的
- CreateThread参数失败
- 在CreateProcess中传递命令行参数失败