代码之家  ›  专栏  ›  技术社区  ›  bers

我如何(static_)断言字符串不是类型?

  •  0
  • bers  · 技术社区  · 2 年前

    我在一个有很多头文件的环境中工作,其中一些头文件有时会 using namespace std; 偷偷溜进来。我想(在CI中)抓到。检查某些东西是否存在/编译很容易,但相反却出奇地困难。

    我的想法是:

    #include "header1.h"
    #include "header2.h"
    // ...
    
    static_assert(!type_is_defined(string))
    

    我该怎么写 type_is_defined 以便在以下情况下编译 string 定义?

    3 回复  |  直到 2 年前
        1
  •  3
  •   Eugene    2 年前

    这可能不是最优雅的方式,但它奏效了:

    #include <string>
    #include <type_traits>
    
    //... many headers here, some of which may contain 'using namespace std;'
    //using namespace std; //uncommenting it causes compiler error: "reference to 'string' is ambiguous" 
    
    class string;
    static_assert(!std::same_as<string, std::string>);
    

    这个 static_assert 需要C++20,因为 same_as 概念。对于C++17,您需要将其替换为 is_same_v .如果您使用早期的C++版本,则可以使用以下内容(适用于C++11):

    static_assert(!std::is_same<string, std::string>::value, "!");
    
        2
  •  0
  •   bers    2 年前

    这里有一个解决方案:

    #include <string>
    
    // using std::string;
    // using namespace std;
    
    // Verify that string is not defined
    // Fails with "redeclared as different kind of entity" if "using std::string"
    void string() {}
    void verify_string_undefined() {
        // Fails with "ambiguous reference" if "using namespace std"
        string();
    }
    
    int main() {}
    

    一旦第3行或第4行取消注释,就无法编译。

    不幸的是,这不允许使用 using std::string 和使用 string 检查之后。

        3
  •  0
  •   Sir Nate    2 年前

    我在一个有很多头文件的环境中工作,其中一些有时是使用名称空间std;偷偷溜进来。我想(在CI中)抓到。

    如果这实际上是你的问题,而不是关于类型字符串,那么你可以这样做:

    #include <charconv>
    #include <type_traits>
    
    // Define a non-existent overload of an std::function with a type that can be converted from the actual signature
    // Make sure to use a different return type
    static int to_chars( char*, char*, bool ){return 0;}
     
    int main() {
        // using namespace std; static assert will fail with this in place
    
        static_assert(std::is_same_v<int,
        // Make sure to use the type for the std:: signature here, 
        // not your custom function's converted type. So 1.0f and not true
        decltype(to_chars(std::declval<char*>(),std::declval<char*>(),1.0f))
        >, "using namespace std when we should not be");
    }