【问题标题】:Clang unknown class name 'exception'Clang 未知类名“异常”
【发布时间】:2014-06-22 13:51:34
【问题描述】:

由于某些奇怪的原因,我很难在 C++ 中抛出异常。我在没有从 stdexcept 头文件中捕获 std::invalid_argument 的情况下抛出。我没有真正的捕捉意图,因为如果发生错误,我希望应用程序无论如何都会失败。

在我将函数定义类#included 到标头声明的命名空间之前,它似乎工作正常。它是在命名空间之前添加的,因为它们是模板定义,我想将标题与其定义分开;然而,我意识到这引起了一个我直到最近才意识到的微妙问题。

他们是我缺少的东西吗?我正在使用clang btw

Project Compilation
.
.
.
.
.
Compiling CPP file TrieTest.cpp ...
In file included from TrieTest.cpp:4:
In file included from ./Trie.hpp:62:
In file included from ./Trie.cpp:2:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/stdexcept:55:30: error: unknown class name 'exception'; did you mean
      '::std::exception'?
  class logic_error : public exception 
                             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/exception:60:9: note: '::std::exception' declared here
  class exception
        ^
In file included from TrieTest.cpp:4:
In file included from ./Trie.hpp:62:
In file included from ./Trie.cpp:2:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/stdexcept:112:32: error: expected class name
  class runtime_error : public exception 
                               ^
2 errors generated.

编辑: 一点 src 我也编译 clang++ -Wall -Wextra -g -std=c++11 TrieTest.cpp -o TrieTest;

“Trie.h”

#ifndef COM_WORDGAME_UTILITY_TRIE_HPP
#define COM_WORDGAME_UTILITY_TRIE_HPP
#include <string>
using std::string;

namespace wordgame_utility{
template<typename value>
class Trie{

      ...Trie Function Declarations

};

//The compiler may not complain initialliy however
//Templates cause visibility issues with user code and is normally defined in the header
//this is a work around 
#include "Trie.cpp"
}

#endif

"Trie.cpp" 头 -n 8

#include "Trie.hpp"
#include <stdexcept>

using namespace wordgame_utility;

template<typename value>
using TrieNode = typename Trie<value>::TrieNode;
...Trie Function Definitions

【问题讨论】:

  • '我缺少他们的东西吗?我正在使用clang btw'很难看到没有看到实际发生错误的代码。您是否只是错过了#include &lt;exception&gt; 或错过了指定命名空间std::exception?或者作为另一个可能的错误来源:您是否使用-std=C++11 标志进行编译?
  • @πάνταῥεῖ:stdexcept 是标准标头,所以这有点奇怪。标头中的代码应该是自给自足的,但它可能已经被混淆了,或者它们可能是 libstdc++ 标头和 clang 的选项之间的不匹配。
  • 你没有把你的#include &lt;exception&gt; 放在一个命名空间里吗?
  • 你能上传一个导致这个错误的代码示例吗(我想它应该是#include &lt;stdexcept&gt;的顺序,然后上传到gist.github.com或类似clang -E test.cc的输出?另外,您安装了哪个版本的 libstdc++?
  • 感谢您的快速回复............我添加了部分来源我原本不想让问题太长............ ...我用 clang++ -Wall -Wextra -g -std=c++11 TrieTest.cpp -o TrieTest 编译;

标签: c++ c++11 exception-handling clang


【解决方案1】:

您的代码中有一个循环包含。

Trie.hpp 包括 Trie.cpp,其中包括 Trie.hpp。这不适用于 C++,其中 include 是文字包含(想想,在 #include 指令的位置复制/粘贴包含的文件)。

您需要将模板方法定义到头文件中,或者到第三个文件中,仅此而已。


这个循环的效果是什么?一般来说,错误消息很糟糕,您可以自己看到。

在你的情况下......让我们自己玩预处理器:

// begin #include "Trie.hpp"
#define COM_WORDGAME_UTILITY_TRIE_HPP

// begin #include <string>
namespace std {
    ...
}
// end #include <string>

using std::string;

namespace wordgame_utility{
    template<typename value>
    class Trie{

      ...Trie Function Declarations

    };

    //The compiler may not complain initialliy however
    //Templates cause visibility issues with user code
    // and is normally defined in the header
    //this is a work around 

// begin #include "Trie.cpp"

// begin #include "Trie.hpp"
// -- empty because of the include guards --
// end #include "Trie.hpp"

// begin #include <stdexcept>
    namespace std {
        class logic_exception: public exception { };
    }
// end #include <stdexcept>

    using namespace wordgame_utility;

    template<typename value>
    using TrieNode = typename Trie<value>::TrieNode;
    ...Trie Function Definitions

// end #include "Trie.cpp"

} // namespace wordgame_utility

// end #include "Trie.hpp"

如您所见,这是一团糟。在开放的命名空间中使用 #include 和循环包含的组合非常丑陋。

幸运的是,在(近?)将来,如果采用模块,这将得到改善,这只是文本包含的更明智的替代方案。

【讨论】:

  • 是和不是。循环包含并不能直接解释这个特定的错误。解释这个特定错误的原因是 Trie.cpp 的包含发生在 namespace wordgame_utility { ... } 块内,而递归包含的 Trie.cpp 然后尝试在命名空间内包含标准库头。 (但我不会将其作为单独的答案发布,因为分辨率与您的答案完全相同。)
  • @Matthieu M. 啊,是的,从问题开始我就想到了,一旦我在命名空间中添加了包含;但是,我这样做有两个原因。包含实际上不会导致循环。但是,如果我删除包含并将 Trie.cpp 添加到我的编译列表中,则会形成一个循环,我发现这是因为模板。
  • @hvd 第二次我将它添加到命名空间,因为在 Trie.cpp 中,由于某种原因,使用声明与我添加 Trie.h 的任何其他文件冲突。我可以简单地删除 using 声明并手动输入类路径,看来我现在必须这样做。
  • @Bonechilla:包含确实会导致循环:Trie.cpp 包括 Trie.hpp,其中包括 Trie.cpp。这完全是一个循环。定义模板类/方法的常用方法是直接将它们定义到.hpp 中,或者在单独的第三个文件中定义(例如Trie.ii)并将那个 文件包含到Trie.hpp 中.另外,我建议不要在命名空间中使用#include,因为预处理器是 dumb 文本包含,它不知道命名空间是什么,因此在编译器面前留下了混乱.
  • @Bonechilla: 或者您可以将所有模板代码放在头文件的底部,或者更喜欢使用Trie-template.hpp 作为名称或其他名称。还有一点需要注意:将using namespace 声明放在头文件的顶层(在方法定义中很好)被认为是不礼貌的,因为它会感染包含代码的所有文件;相反,我建议您重新打开命名空间。
猜你喜欢
  • 1970-01-01
  • 2013-07-03
  • 1970-01-01
  • 2014-08-11
  • 2018-08-25
  • 2013-10-27
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
相关资源
最近更新 更多