为什么允许我显式实例化模板特化,其中默认参数不能隐式转换为其他类型?
Why am I allowed to explicitly instantiate a template specialization where the default argument is not implicitly convertible to the other type?
见以下代码:
#include <iostream>
template<typename T = int>
void func(T t = 1)
{
std::cout << t << std::endl;
}
template void func<int>(int); // Explicit instantion of `int`
template void func<std::string>(std::string); // Explicit instantiation of `std::string` -- why does this not give the same error as below?
int main()
{
func(); // Outputs "1" - OK
func(std::string("test")); // Outputs "test" - OK
// func<std::string>(); // Explicit instantiation - Fails (as expected!): could not convert '1' from 'int' to 'std::string'
}
我原以为 template void func<std::string>(std::string);
行是非法的,因为默认的 int
参数不能隐式转换为 std::string
(类似于我得到编译的方式上次调用时出错),并且我将不得不求助于 this answer.
中概述的解决方案
当我有一个带有默认参数的函数模板时,为什么允许我显式实例化一个默认参数不能隐式转换为其他类型的模板特化? 这结果正是我想要的,但我很想知道编译器是如何计算出来的。
默认模板参数及其默认值是为函数模板指定的func
,这意味着它们仅在模板未使用任何类型和值实例化时才被考虑。
所以func(std::string("test"));
调用使用模板的显式实例化std::string
并成功。
而 func<std::string>();
将失败,因为使用 std::string
模板的显式实例化但参数的默认值为 1
(这是一个 int
) .
这相当于:
func<std::string>(1);
并且编译器 (GCC 8.2) 对这两个调用报告相同的错误。
<source>:18:23: note: cannot convert '1' (type 'int') to type 'std::__cxx11::basic_string<char>'
查看演示 here。
见以下代码:
#include <iostream>
template<typename T = int>
void func(T t = 1)
{
std::cout << t << std::endl;
}
template void func<int>(int); // Explicit instantion of `int`
template void func<std::string>(std::string); // Explicit instantiation of `std::string` -- why does this not give the same error as below?
int main()
{
func(); // Outputs "1" - OK
func(std::string("test")); // Outputs "test" - OK
// func<std::string>(); // Explicit instantiation - Fails (as expected!): could not convert '1' from 'int' to 'std::string'
}
我原以为 template void func<std::string>(std::string);
行是非法的,因为默认的 int
参数不能隐式转换为 std::string
(类似于我得到编译的方式上次调用时出错),并且我将不得不求助于 this answer.
当我有一个带有默认参数的函数模板时,为什么允许我显式实例化一个默认参数不能隐式转换为其他类型的模板特化? 这结果正是我想要的,但我很想知道编译器是如何计算出来的。
默认模板参数及其默认值是为函数模板指定的func
,这意味着它们仅在模板未使用任何类型和值实例化时才被考虑。
所以func(std::string("test"));
调用使用模板的显式实例化std::string
并成功。
而 func<std::string>();
将失败,因为使用 std::string
模板的显式实例化但参数的默认值为 1
(这是一个 int
) .
这相当于:
func<std::string>(1);
并且编译器 (GCC 8.2) 对这两个调用报告相同的错误。
<source>:18:23: note: cannot convert '1' (type 'int') to type 'std::__cxx11::basic_string<char>'
查看演示 here。