模板编程的错误信息非常难读,例如下面例子
#include <iostream>
template <typename T>
T multiply(T first, T second)
{
return first * second;
}
int main()
{
std::cout << multiply(3, 5) << std::endl;
std::cout << multiply("1", "2") << std::endl;
}
在倒数第二行,我们传入了错误的参数,他的报错是这样的
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2296: '*': not valid as left operand has type 'T'
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2296: with
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2296: [
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2296: T=const char *
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2296: ]
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22):
1>the template instantiation context (the oldest one first) is
1> E:\codes\TestCpp\TestCpp\main.cpp(12,18):
1> see reference to function template instantiation 'T *multiply<const char*>(T,T)' being compiled
1> with
1> [
1> T=const char *
1> ]
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2297: '*': not valid as right operand has type 'T'
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2297: with
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2297: [
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2297: T=const char *
1>E:\codes\TestCpp\TestCpp\main.cpp(6,22): error C2297: ]
1>Done building project "TestCpp.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
如果我们使用requires子句约束模板,错误信息可读性就会高很多,我们上面的程序改成这样:
#include <iostream>
template <typename T>
requires std::integral<T> || std::floating_point<T>
T multiply(T first, T second)
{
return first * second;
}
int main()
{
std::cout << multiply(3, 5) << std::endl;
std::cout << multiply("1", "2") << std::endl;
}
这个时候不需要编译,ide已经提示我们输入了错了的参数,如果我们编译一下
1>E:\codes\TestCpp\TestCpp\main.cpp(13,18): error C2672: 'multiply': no matching overloaded function found
1>E:\codes\TestCpp\TestCpp\main.cpp(5,7):
1>could be 'T multiply(T,T)'
1> E:\codes\TestCpp\TestCpp\main.cpp(13,18):
1> the associated constraints are not satisfied
1> E:\codes\TestCpp\TestCpp\main.cpp(4,10):
1> the concept 'std::integral<const char*>' evaluated to false
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\concepts(70,20):
1> the constraint was not satisfied
1> E:\codes\TestCpp\TestCpp\main.cpp(4,30):
1> the concept 'std::floating_point<const char*>' evaluated to false
1> C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\concepts(79,26):
1> the constraint was not satisfied
1>Done building project "TestCpp.vcxproj" -- FAILED.
错误信息简单了很多
如果我们对模板的约束很多,岂不是会有一个超级长的声明?
这个问题可以用concept解决!
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
template <typename T>
requires Numeric<T>
T multiply(T first, T second)
{
return first * second;
}
更简单一点,直接写成
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
template <Numeric T>
T multiply(T first, T second)
{
return first * second;
}
更简单一点,auto大法好!
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
auto multiply(Numeric auto first, Numeric auto second)
{
return first * second;
}