Как утверждать во время компиляции, что функция является членом определенного класса

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

Можно ли во время компиляции утверждать, что функция, использующая этот конкретный макрос, является членом определенного класса? Доступны функции C++03 или Boost.

#define MACRO_OF_THE_DOOM(...) assertion_here(); do_something();

class A {
    void functionA();
    void functionB();
};

// This is valid usage
void A::functionA() {
    MACRO_OF_THE_DOOM(1, 2, 3, 4, 5);
}

// This should give an understandable compile error, which tells
// definition should be A::functionB()
void functionB() {
    MACRO_OF_THE_DOOM(6, 7, 8);
}

person vll    schedule 28.04.2016    source источник
comment
Итак, настоящая причина этого заключается в том, что вы все время забываете добавлять к своим функциям префикс A:: при их реализации? Вы пробовали -Wall?   -  person Bartek Banachewicz    schedule 28.04.2016
comment
@BartekBanachewicz Я думаю, что в этом случае статическое утверждение будет лучше, чем -Wall, потому что ошибки компиляции отображаются перед предупреждениями компилятора. Меня также интересует, теоретически возможно ли это сделать со статическим утверждением.   -  person vll    schedule 28.04.2016
comment
@BartekBanachewicz Кроме того, кажется, что компилятор, который я использую, не предупреждает о подобных проблемах.   -  person vll    schedule 28.04.2016
comment
Вы ищете что-то более сложное, чем #define MAKRO_OF_DOOM(p1,p2,p3) /** in case of error: check that function is member of Foo **/ ((Foo*)this)->someOtherFun(); ?   -  person VolkerK    schedule 28.04.2016
comment
@ВолкерК Да; в вашем примере ошибка компиляции будет отображаться в строке, в которой используется макрос. Программист никогда не прочитает определение макроса (и не увидит комментарий). Поэтому было бы полезно иметь понятное сообщение об ошибке.   -  person vll    schedule 28.04.2016
comment
Какой компилятор вы используете? см. rextester.com/NKMW16046   -  person VolkerK    schedule 28.04.2016
comment
@VolkerK Ах, я не понял, какое сообщение об ошибке выдает. В моем случае может быть достаточно сообщения о том, что functionB не является функцией-членом. Возможно, вам следует опубликовать это как ответ.   -  person vll    schedule 28.04.2016


Ответы (2)


arrow_upward
1
arrow_downward

Вы можете использовать BOOST_STATIC_ASSERT.

#define MACRO_OF_THE_DOOM(...)  { assertion_here(); do_something(); }

assertion_here() { BOOST_STATIC_ASSERT(false); }
class A {
    assertion_here() { // no-op }
    void functionA();
    void functionB();
};

Есть несколько предостережений по этому поводу, которые можно обойти с помощью type_traits, но этого решения может быть достаточно для многих случаев.

person bashrc    schedule 28.04.2016

arrow_upward
1
arrow_downward

Можно ли во время компиляции утверждать, что функция, использующая этот конкретный макрос, является членом определенного класса?

Если вам доступен boost (я понимаю, что вы не можете использовать c++11), то я предлагаю Библиотека TTI. Ниже пример с комментариями:

http://coliru.stacked-crooked.com/a/66a5016a1d02117c

#include <iostream>

#include <boost/tti/has_member_function.hpp>
#include <boost/static_assert.hpp>

BOOST_TTI_HAS_MEMBER_FUNCTION(functionA)
BOOST_TTI_HAS_MEMBER_FUNCTION(functionB)

class A {
public: // must be public for tti
    void functionA();
    //void functionB();
};

int main()
{
    // prints 1
    std::cout << has_member_function_functionA<
       A, // class type to check
       void,    // function return type
       boost::mpl::vector<> >::value // parameter list
       << std::endl;

    // Below generates no compile error - prints 0
    std::cout << has_member_function_functionB<
       A, // class type to check
       void,    // function return type
       boost::mpl::vector<> >::value // parameter list
       << std::endl;

    // Below static assertion, will fail at compile time
    BOOST_STATIC_ASSERT(
        (has_member_function_functionB<A,void,boost::mpl::vector<> >::value));

}

Я обновил его, чтобы сделать его совместимым с С++ 03, к сожалению, статическое утверждение без С++ 11 генерирует довольно критическое сообщение:

main.cpp: In function 'int main()':
main.cpp:32:5: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'
     BOOST_STATIC_ASSERT(
     ^
main.cpp:32:5: error: template argument 1 is invalid
     BOOST_STATIC_ASSERT(
     ^
person marcinj    schedule 28.04.2016