Этот макрос может быть преобразован в функцию?

Другим совершенно другим способом является точка монтирования в uwsgi.

Из документа doc about Хостинг нескольких приложений в одном и том же процессе ( permalink ).

В вашем uwsgi.ini вы добавляете

[uwsgi]
mount = /foo=main.py
manage-script-name = true

# also stuff which is not relevant for this, but included for completeness sake:    
module = main
callable = app
socket = /tmp/uwsgi.sock

Если вы не вызываете свой файл main.py, вам необходимо изменить оба mount и module

Ваш main.py может выглядеть так:

from flask import Flask, url_for
app = Flask(__name__)
@app.route('/bar')
def bar():
  return "The URL for this page is {}".format(url_for('bar'))
# end def

И конфигурация nginx (опять же для полноты):

server {
  listen 80;
  server_name example.com

  location /foo {
    include uwsgi_params;
    uwsgi_pass unix:///temp/uwsgi.sock;
  }
}

Теперь вызов example.com/foo/bar отобразит /foo/bar, как возвращено флягой url_for('bar'), так как оно автоматически адаптируется. Таким образом, ваши ссылки будут работать без проблем с префиксами.

8
задан Brian Tompsett - 汤莱恩 27 November 2015 в 11:17
поделиться

16 ответов

Как указано, код на самом деле разрабатывают число элементов в массиве, не структуру. Я просто выписал бы sizeof () подразделение явно, когда я хочу это. Если бы я должен был сделать это функцией, то я хотел бы прояснить в ее определении, что это ожидает массив.

template<typename T,int SIZE>
inline size_t array_size(const T (&array)[SIZE])
{
    return SIZE;
}

Вышеупомянутое подобно xtofl's, кроме него принимает меры против передачи указателя на него (который говорит что точка динамично выделенному массиву), и получение неправильного ответа по ошибке.

Править: Упрощенный согласно JohnMcG. Править: встроенный.

К сожалению, вышеупомянутое не предоставляет ответ времени компиляции (даже если компилятор действительно встраивает и оптимизирует его, чтобы быть константой под капотом), так не может использоваться в качестве константного выражения времени компиляции. т.е. Это не может использоваться в качестве размера для объявления статического массива. Под C++ 0x, уходит эта проблема, если Вы заменяете ключевое слово, встроенное constexpr (constexpr, встроено неявно).

constexpr size_t array_size(const T (&array)[SIZE])

решение jwfearn работает в течение времени компиляции, но включает наличие определения типа, которое эффективно "сохранило" размер массива в объявлении нового имени. Размер массива затем разработан путем инициализации константы через то новое имя. В таком случае можно также просто сохранить размер массива в константу от запуска.

Отправленное решение Martin York также работает под временем компиляции, но включает использование нестандартного typeof () оператор. Работа вокруг к этому, любой ожидают C++ 0x и используют decltype (которым временем нельзя было бы на самом деле быть нужен он для этой проблемы, поскольку у нас будет constexpr). Другая альтернатива должна использовать Повышение. Typeof, в этом случае мы закончим с

#include <boost/typeof/typeof.hpp>

template<typename T>
struct ArraySize
{
    private:    static T x;
    public:     enum { size = sizeof(T)/sizeof(*x)};
};
template<typename T>
struct ArraySize<T*> {};

и используется путем записи

ArraySize<BOOST_TYPEOF(foo)>::size

где нечто является названием массива.

19
ответ дан 5 December 2019 в 05:00
поделиться

Для массивов переменной длины C99-стиля кажется, что чистый макро-подход (sizeof (прибытие) / sizeof (прибытие [0])) является единственным, который будет работать.

0
ответ дан 5 December 2019 в 05:00
поделиться

Конкретный Windows:

Существует макрос _countof() предоставленный CRT точно с этой целью.

Ссылка на документ в MSDN

0
ответ дан 5 December 2019 в 05:00
поделиться
0
ответ дан 5 December 2019 в 05:00
поделиться

Как ответ JohnMcG, но

Недостаток - Вы, будет иметь копию этого в Вашем двоичном файле для каждого Имени типа, комбинации Размера.

Вот почему Вы сделали бы это встроенной шаблонной функцией.

0
ответ дан 5 December 2019 в 05:00
поделиться

xtofl имеет правильный ответ для нахождения размера массива. Никакой макрос или шаблон не должны быть необходимыми для нахождения размера структуры, так как sizeof () должен сделать приятно.

Я соглашаюсь, что препроцессор является злым, но существуют случаи, где это является наименее злым из альтернатив.

0
ответ дан 5 December 2019 в 05:00
поделиться

Я предпочитаю перечислимый метод, предложенный [BCS] (в этом макросе, может быть преобразован в функцию?)

Это вызвано тем, что можно использовать его, где компилятор ожидает постоянное время компиляции. Текущая версия языка не позволяет Вам использовать результаты функций за время компиляции consts, но я верю этому прибытию в следующую версию компилятора:

Проблема с этим методом состоит в том, что он не генерирует ошибку времени компиляции при использовании с классом, который перегрузился '*' оператор (см. код ниже для деталей).

К сожалению, версия, предоставленная 'BCS', действительно не совсем компилирует как ожидалось, таким образом, вот моя версия:

#include <iterator>
#include <algorithm>
#include <iostream>


template<typename T>
struct StructSize
{
    private:    static T x;
    public:      enum { size = sizeof(T)/sizeof(*x)};
};

template<typename T>
struct StructSize<T*>
{
    /* Can only guarantee 1 item (maybe we should even disallow this situation) */
    //public:     enum { size = 1};
};

struct X
{
    int operator *();
};


int main(int argc,char* argv[])
{
    int data[]                                  = {1,2,3,4,5,6,7,8};
    int copy[ StructSize<typeof(data)>::size];

    std::copy(&data[0],&data[StructSize<typeof(data)>::size],&copy[0]);
    std::copy(&copy[0],&copy[StructSize<typeof(copy)>::size],std::ostream_iterator<int>(std::cout,","));

    /*
     * For extra points we should make the following cause the compiler to generate an error message */
    X   bad1;
    X   bad2[StructSize<typeof(bad1)>::size];
}
1
ответ дан 5 December 2019 в 05:00
поделиться

Да это может быть сделано шаблоном в C++

template <typename T>
size_t getTypeSize()
{
   return sizeof(T)/sizeof(*T);
}

использовать:

struct JibbaJabba
{
   int int1;
   float f;
};

int main()
{
    cout << "sizeof JibbaJabba is " << getTypeSize<JibbaJabba>() << std::endl;
    return 0;
}

См. сообщение BCS выше или ниже о прохладном способе сделать это с классом во время компиляции с помощью некоторого легкого шаблонного метапрограммирования.

0
ответ дан 5 December 2019 в 05:00
поделиться

Я не думаю, что это действительно разрабатывает число элементов в структуре. Если структура упаковывается, и Вы использовали вещи, меньшие, чем размер указателя (такие как символ в 32-разрядной системе) затем, Ваши результаты являются неправильными. Кроме того, если структура содержит структуру, Вы неправы также!

0
ответ дан 5 December 2019 в 05:00
поделиться

@KTC Simplfying, так как у нас есть размер массива в аргументе шаблона:

template<typename T, int SIZE>
int arraySize(const T(&arr)[SIZE])
{
    return SIZE;
}

Недостаток - Вы, будет иметь копию этого в Вашем двоичном файле для каждого Имени типа, комбинации Размера.

1
ответ дан 5 December 2019 в 05:00
поделиться

Тип шаблонной функции выведен автоматически, в отличие от типа шаблонного класса. Можно использовать его еще более простой:

template< typename T > size_t structsize( const T& t ) { 
  return sizeof( t ) / sizeof( *t ); 
}


int ints[] = { 1,2,3 };
assert( structsize( ints ) == 3 );

Но я соглашаюсь, что это не работает на структуры: это работает на массивы. Таким образом, я назвал бы это Arraysize :)

1
ответ дан 5 December 2019 в 05:00
поделиться

Ваш макрос неверно называется, это нужно назвать ARRAYSIZE. Это используется для определения числа элементов в массиве, кто размер, фиксируется во время компиляции. Вот способ, которым это может работать:

символьное нечто [128];//В действительности, у Вас было бы некоторое константное или константное выражение как размер массива.

для (неподписанный я = 0; я <STRUCTSIZE (нечто); ++ i) {}

Это является довольно хрупким для использования, потому что можно сделать эту ошибку:

символ* нечто = новый символ [128];

для (неподписанный я = 0; я <STRUCTSIZE (нечто); ++ i) {}

Вы теперь выполните итерации, поскольку я = 0 к <1 и отрываю Ваши волосы.

1
ответ дан 5 December 2019 в 05:00
поделиться

Макрос имеет очень вводящее в заблуждение имя - выражение в макросе возвратит число элементов в массиве, если имя массива будет передано в как макро-параметр.

Для других типов Вы получите что-то более или менее бессмысленное, если тип будет указателем, или Вы получите синтаксическую ошибку.

Обычно тот макрос называют чем-то как NUM_ELEMENTS () или чем-то для указания на его истинную полноценность. Не возможно заменить макрос функцией в C, но в C++ может использоваться шаблон.

Версия, которую я использую, основана на коде в winnt.h заголовке Microsoft (сообщает мне, если регистрация этого отрывка идет вне добросовестного использования):

//
// Return the number of elements in a statically sized array.
//   DWORD Buffer[100];
//   RTL_NUMBER_OF(Buffer) == 100
// This is also popularly known as: NUMBER_OF, ARRSIZE, _countof, NELEM, etc.
//
#define RTL_NUMBER_OF_V1(A) (sizeof(A)/sizeof((A)[0]))

#if defined(__cplusplus) && \
    !defined(MIDL_PASS) && \
    !defined(RC_INVOKED) && \
    !defined(_PREFAST_) && \
    (_MSC_FULL_VER >= 13009466) && \
    !defined(SORTPP_PASS)
//
// RtlpNumberOf is a function that takes a reference to an array of N Ts.
//
// typedef T array_of_T[N];
// typedef array_of_T &reference_to_array_of_T;
//
// RtlpNumberOf returns a pointer to an array of N chars.
// We could return a reference instead of a pointer but older compilers do not accept that.
//
// typedef char array_of_char[N];
// typedef array_of_char *pointer_to_array_of_char;
//
// sizeof(array_of_char) == N
// sizeof(*pointer_to_array_of_char) == N
//
// pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T);
//
// We never even call RtlpNumberOf, we just take the size of dereferencing its return type.
// We do not even implement RtlpNumberOf, we just decare it.
//
// Attempts to pass pointers instead of arrays to this macro result in compile time errors.
// That is the point.
//
extern "C++" // templates cannot be declared to have 'C' linkage
template <typename T, size_t N>
char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];

#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))

//
// This does not work with:
//
// void Foo()
// {
//    struct { int x; } y[2];
//    RTL_NUMBER_OF_V2(y); // illegal use of anonymous local type in template instantiation
// }
//
// You must instead do:
//
// struct Foo1 { int x; };
//
// void Foo()
// {
//    Foo1 y[2];
//    RTL_NUMBER_OF_V2(y); // ok
// }
//
// OR
//
// void Foo()
// {
//    struct { int x; } y[2];
//    RTL_NUMBER_OF_V1(y); // ok
// }
//
// OR
//
// void Foo()
// {
//    struct { int x; } y[2];
//    _ARRAYSIZE(y); // ok
// }
//

#else
#define RTL_NUMBER_OF_V2(A) RTL_NUMBER_OF_V1(A)
#endif

#ifdef ENABLE_RTL_NUMBER_OF_V2
#define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V2(A)
#else
#define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V1(A)
#endif

//
// ARRAYSIZE is more readable version of RTL_NUMBER_OF_V2, and uses
// it regardless of ENABLE_RTL_NUMBER_OF_V2
//
// _ARRAYSIZE is a version useful for anonymous types
//
#define ARRAYSIZE(A)    RTL_NUMBER_OF_V2(A)
#define _ARRAYSIZE(A)   RTL_NUMBER_OF_V1(A)

Кроме того, книга Matthew Wilson "Имперфект, C++" имеет хорошую обработку того, что продолжается здесь (Раздел 14.3 - страница 211-213 - Массивы и Указатели - dimensionof ()).

2
ответ дан 5 December 2019 в 05:00
поделиться

Решение KTC является чистым, но оно не может использоваться во время компиляции, и это зависит от компиляторной оптимизации для предотвращения чрезмерного увеличения размера кода и вызова функции наверху.

Можно вычислить размер массива с единственной временем компиляции метафункцией с нулевой стоимостью во время выполнения. BCS был на правильном пути, но то решение является неправильным.

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

// asize.hpp
template < typename T >
struct asize; // no implementation for all types...

template < typename T, size_t N >
struct asize< T[N] > { // ...except arrays
    static const size_t val = N;
};

template< size_t N  >
struct count_type { char val[N]; };

template< typename T, size_t N >
count_type< N > count( const T (&)[N] ) {}

#define ASIZE( a ) ( sizeof( count( a ).val ) ) 
#define ASIZET( A ) ( asize< A >::val ) 

с тестовым кодом (использующий Повышение. StaticAssert для демонстрации единственного временем компиляции использования):

// asize_test.cpp
#include <boost/static_assert.hpp>
#include "asize.hpp"

#define OLD_ASIZE( a ) ( sizeof( a ) / sizeof( *a ) )

typedef char C;
typedef struct { int i; double d; } S;
typedef C A[42];
typedef S B[42];
typedef C * PA;
typedef S * PB;

int main() {
    A a; B b; PA pa; PB pb;
    BOOST_STATIC_ASSERT( ASIZET( A ) == 42 );
    BOOST_STATIC_ASSERT( ASIZET( B ) == 42 );
    BOOST_STATIC_ASSERT( ASIZET( A ) == OLD_ASIZE( a ) );
    BOOST_STATIC_ASSERT( ASIZET( B ) == OLD_ASIZE( b ) );
    BOOST_STATIC_ASSERT( ASIZE( a ) == OLD_ASIZE( a ) );
    BOOST_STATIC_ASSERT( ASIZE( b ) == OLD_ASIZE( b ) );
    BOOST_STATIC_ASSERT( OLD_ASIZE( pa ) != 42 ); // logic error: pointer accepted
    BOOST_STATIC_ASSERT( OLD_ASIZE( pb ) != 42 ); // logic error: pointer accepted
 // BOOST_STATIC_ASSERT( ASIZE( pa ) != 42 ); // compile error: pointer rejected
 // BOOST_STATIC_ASSERT( ASIZE( pb ) != 42 ); // compile error: pointer rejected
    return 0;
}

Это решение отклоняет нетипы массива во время компиляции, таким образом, оно не запутается указателями, как макро-версия делает.

5
ответ дан 5 December 2019 в 05:00
поделиться

Ни один до сих пор не предложил портативный способ получить размер массива, когда у Вас только есть экземпляр массива и не его типа. (typeof и _countof не является портативным, так не может использоваться.)

Я сделал бы это следующий путь:

template<int n>
struct char_array_wrapper{
    char result[n];
};

template<typename T, int s>
char_array_wrapper<s> the_type_of_the_variable_is_not_an_array(const T (&array)[s]){
}


#define ARRAYSIZE_OF_VAR(v) sizeof(the_type_of_the_variable_is_not_an_array(v).result)

#include <iostream>
using namespace std;

int main(){
    int foo[42];
    int*bar;
    cout<<ARRAYSIZE_OF_VAR(foo)<<endl;
    // cout<<ARRAYSIZE_OF_VAR(bar)<<endl;  fails
}
  • Это работает, когда только значение вокруг.
  • Это портативно и только использует C++ станд.
  • Это перестало работать с descriptiv сообщением об ошибке.
  • Это не оценивает значение. (Я не могу продумать ситуации, где это было бы проблемой, потому что тип массива не может быть возвращен функцией, но лучше быть безопасным, чем извините.)
  • Это возвращает размер как постоянное время компиляции.

Я перенес конструкцию в макрос, чтобы иметь некоторый достойный синтаксис. Если Вы хотите избавиться от него, Ваша единственная опция состоит в том, чтобы сделать замену вручную.

5
ответ дан 5 December 2019 в 05:00
поделиться
  • функция, никакая шаблонная функция, да
  • шаблон, я думаю так (но C++
  • шаблоны не являются моей вещью),

Править: Из кода Doug

template <typename T>
uint32_t StructSize()  // This might get inlined to a constant at compile time
{
   return sizeof(T)/sizeof(*T);
}

// or to get it at compile time for shure

class StructSize<typename T>
{
   enum { result = sizeof(T)/sizeof(*T) };
}

Мне сказали, что 2-й не работает. OTOH что-то как он должно быть осуществимо, я просто, не используют C++ достаточно для фиксации его.

Страница на C++ (и D) обрабатывает по шаблону для материала времени компиляции

1
ответ дан 5 December 2019 в 05:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: