gpt4 book ai didi

具有 static_assert 的 C++ 模板在错误的位置显示编译错误

转载 作者:行者123 更新时间:2023-11-30 04:01:24 28 4
gpt4 key购买 nike

我正在学习 C++,但对其模板的工作方式感到有些困惑。让我举个例子,这是有效的:

#include <iostream>
#include <cstdlib>
#include <type_traits>

template <class T> const T first(const T& first, const T& second) {
return first.size()<second.size() ? first : second;
}

int main(int argc, char** argv) {
std::string x = "the short string";
std::string y = "the longer string";
std::cout << "first of x, y is "<<first(y,x)<<std::endl;
}

上面的代码可以工作,但是什么能阻止我使用整数作为我的模板参数呢?

int main(int argc, char** argv) {
int x = 3;
int y = 8;
std::cout << "first of x, y is "<<first(y,x)<<std::endl;
}

进行上述更改会在“first”方法而非“main”方法中产生编译错误。我读了here我可以使用 static_assert 语句来处理这个问题,但我不知道如何在编译时检查类型 T 是 basic_string 还是子类

我想知道当我使用 static_assert 时,C++ 是否会在正确的位置报告问题,所以我将问题换成了这样:

template <class T> const T first_numeric(const T& first, const T& second) {
static_assert(std::is_arithmetic<T>::value,"You must use a number!");
return first<second ? first : second;
}

int main(int argc, char** argv) {
// int x = 3;
// int y = 8;
// std::cout << "first_numeric of x, y is "<<first_numeric(y,x)<<std::endl;
std::string x = "3";
std::string y = "8";
std::cout << "first_numeric of x, y is "<<first_numeric(y,x)<<std::endl;
}

如果我从上面的例子开始这个问题,我不可避免地会被告知“你到底为什么要限制类型参数?”希望你现在明白了。

在上面的例子中,编译器确实像我们希望的那样失败了,但是它在错误的行上失败了。它在 static_assert 行显示编译错误,而不是我用非法参数调用方法的行。

您可能在想,“那又怎样?”好吧,在这个例子中很明显问题出在哪里,但当您有 10000 行代码时可能就不是这样了。当然,您可以使用 IDE 获取该函数的调用层次结构,但如果调用该方法的地方有数百个,您将检查每一个地方,只是为了找出您的错误。

所以我的问题是:

  1. 有没有办法让 C++ 在使用非法类型参数调用方法的那一行报告编译错误?
  2. 如果没有,您能给我什么指导来避免或解决这个问题?

===============================

更新:这是错误输出

mkdir -p build/Debug/GNU-Linux-x86
rm -f "build/Debug/GNU-Linux-x86/main.o.d"
g++ -c -g -std=c++11 -MMD -MP -MF "build/Debug/GNU-Linux-x86/main.o.d" -o build/Debug/GNU-Linux-x86/main.o main.cpp
main.cpp: In instantiation of ‘const T first_numeric(const T&, const T&) [with T = std::basic_string<char>]’:
main.cpp:22:64: required from here
main.cpp:6:5: error: static assertion failed: You must use a number!
static_assert(std::is_arithmetic<T>::value,"You must use a number!");
^
make[2]: *** [build/Debug/GNU-Linux-x86/main.o] Error 1
make[2]: Leaving directory `/home/mike/NetBeansProjects/CppApplication_1'
make[1]: *** [.build-conf] Error 2
make[1]: Leaving directory `/home/mike/NetBeansProjects/CppApplication_1'
make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 460ms)

显然输出确实提到了真正问题所在的第 22 行,但它没有在源代码中突出显示它。我应该阅读输出,而不是只看突出显示的内容。

最佳答案

这是 GCC 打印的内容:

prog.cc: In instantiation of 'const T first_numeric(const T&, const T&) [with T = std::basic_string<char>]':
prog.cc:16:64: required from here
prog.cc:6:5: error: static assertion failed: You must use a number!
static_assert(std::is_arithmetic<T>::value,"You must use a number!");
^

请注意 prog.cc:16:64: required from here 行?它会告诉您调用模板的位置。

Clang 的错误信息更加清晰:

prog.cc:6:5: error: static_assert failed "You must use a number!"
static_assert(std::is_arithmetic<T>::value,"You must use a number!");
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:16:47: note: in instantiation of function template specialization 'first_numeric<std::__1::basic_string<char> >' requested here
std::cout << "first_numeric of x, y is "<<first_numeric(y,x)<<std::endl;
^

某些 IDE(如 Visual Studio)会在其“错误”窗口中截断错误消息,但 Visual Studio 上的构建输出窗口具有完整的错误消息:

[...]\consoleapplication2.cpp(10): error C2338: You must use a number!
[...]\consoleapplication2.cpp(20) : see reference to function template instantiation 'T first_numeric<std::string>(const T &,const T &)' being compiled
with
[
T=std::string
]

本例中的第 20 行是 main() 中调用 first_numeric 的行。

如果您真的希望错误源自调用函数的行,您可以使用 std::enable_if 或类似机制有选择地禁用函数模板,但这通常会导致 可读性更差,更难理解错误消息。您通常会收到“无匹配函数”错误。

关于具有 static_assert 的 C++ 模板在错误的位置显示编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25778911/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com