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

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

Можно ли во время компиляции утверждать, что функция, использующая этот конкретный макрос, является членом определенного класса? Доступны функции 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)


Вы можете использовать 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

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

Если вам доступен 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