Как я могу (static_) утверждать, что строка не является типом?

Я работаю в среде с множеством заголовочных файлов, в некоторые из которых иногда проникает using namespace std;. Я хочу уловить (в CI), когда это произойдет. Легко проверить, что что-то существует/компилируется, но наоборот на удивление сложно.

Моя идея заключалась в следующем:

#include "header1.h"
#include "header2.h"
// ...

static_assert(!type_is_defined(string))

Как я могу написать type_is_defined так, чтобы он компилировался, когда string не определен?

@463035818_is_not_an_ai "Знаете ли вы, как реализовать type_is_defined(string)?" Нет, это именно мой вопрос. Ты? Ключ находится в положении «так, чтобы он компилировался, когда строка не определена». Какую бы реализацию type_is_defined я ни придумал, все они не скомпилируются, если string не определен, но это тот случай, когда мне нужно успешно скомпилировать.

bers 13.08.2024 21:24

Я думаю, вы имеете в виду следующее: «Легко получить ошибку компилятора, когда что-то не объявлено», потому что для фактической «проверки» необходимо скомпилировать оба случая, и если вы это получите, то «противоположное» на самом деле будет просто отрицанием через !

463035818_is_not_an_ai 13.08.2024 21:24

Возможно, это невозможно, пока в C++ не будет добавлено отражение.

3CxEZiVlQ 13.08.2024 21:24

PS: Я удалил первоначальный комментарий, потому что думаю, что за это время понял, что вы хотите сказать.

463035818_is_not_an_ai 13.08.2024 21:25

мое замешательство связано с тем, что «легко проверить, что что-то существует/компилируется», а вы просите именно об этом;)

463035818_is_not_an_ai 13.08.2024 21:26

@463035818_is_not_an_ai, ну нет. Я не писал «Легко проверить, существует ли что-то/компилируется» (что было бы в обоих случаях). Другими словами, я написал: «Легко проверить, что что-то существует/компилируется» (просто написав это), но «Трудно проверить, что что-то не существует/не скомпилируется, при этом гарантируя, что код компилируется». Теперь это имеет больше смысла?

bers 13.08.2024 21:29

как я писал выше, имхо "проверка" подразумевает, что результат может быть отрицательным или положительным. Ничего, я понял.

463035818_is_not_an_ai 13.08.2024 21:32
using string = int; в глобальном пространстве имен будет использовать string без std::сбоя с ошибкой компилятора, хотя это очень, очень серьезный взлом, который может иметь неприятные последствия. Не проще ли просто добавить еще одно задание CI, которое завершится сбоем, если grep -r "using namespace std;" вернет какие-либо совпадения?
Yksisarvinen 13.08.2024 21:34

вам нужно как минимум объявить string, тогда вы сможете проверить, определен ли он. Однако все попытки, которые я помню, имеют неопределенное поведение.

463035818_is_not_an_ai 13.08.2024 21:44

Я второй @Yksisarvinen. Это задача статического анализа, и ее можно решить, добавив еще один шаг CI, чтобы проверить, существует ли using namespace std; в каждом файле. и ошибки, если он их найдет.

NathanOliver 13.08.2024 21:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
10
61
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Возможно, это не самый элегантный способ, но он работает:

#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, "!");

Это хорошо, но, к сожалению, недоступно до C++20 и потерпит неудачу, если вы объявите using std::string отдельно, даже не включая все пространство имен…

Obsidian 13.08.2024 21:55

@Obsidian, для using std::string это нормально, а я использую C++ 20.

bers 13.08.2024 21:58

@ 463035818_is_not_an_ai, нет, если вы удалите static_assert, декларация не провалится, даже если вы раскомментируете using namespace std

Eugene 13.08.2024 22:07

@Юджин, извини, я виноват, я экспериментировал только с using std::string;

463035818_is_not_an_ai 13.08.2024 22:08

Вот одно решение:

#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 после проверки.

Я работаю в среде с множеством заголовочных файлов, в некоторых из которых иногда используется пространство имен 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");
}

Другие вопросы по теме