2015-03-16 7 views
1

Я проверил следующий код с gcc 4.9.0 и clang 3.5.0. Программа выводит «истина», как ожидалось. Однако, если я удаляю комментарий перед перечислением, он превращается в «ложь». Что здесь происходит? Как я могу убедиться, что has_mem boolean имеет значение true. Моя конечная цель - иметь функцию-член в структуре A, которая включена через enable_if, только если класс T имеет определенную функцию-член.CRTP и Boost TTI

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

BOOST_TTI_HAS_MEMBER_FUNCTION(func) 

template<class T> 
struct A 
{ 
    //enum : bool { has_mem= has_member_function_func<T,void,boost::mpl::vector<const T &> >::value }; 
    A() 
    { 
    std::cout << std::boolalpha 
     << has_member_function_func<T,void,boost::mpl::vector<const T &> >::value 
     << "\n"; 
    } 
}; 

struct B : public A<B> 
{ 
    void func(const B&) {} 
}; 

int main() 
{ 
    B b; 
} 
+0

На первый взгляд, похоже, что результат функции типа memoized в инициализаторе перечисления, а затем снова используется в конструкторе. Обратите внимание, что функция типа в ctor оценивается во время создания экземпляра, что может изменить результат. – dyp

+0

Я думаю, что вы хотите в общем случае невозможно: Рассмотрим [две взаимозависимые функции] (http://coliru.stacked-crooked.com/a/248a53f125124672). В CRTP используется базовое предложение, которое требует создания экземпляра базы до создания экземпляра производного типа. Следовательно, производный тип не может быть проверен внутри экземпляра базового типа. Определение функций-членов (и NSDMI и т. Д.) Создается позже, поэтому они могут проверять производный класс. – dyp

+0

Конечно, вы можете отложить оценку функции типа, например. сделав его оценку зависимой от шаблона-шаблона шаблона участника (функции), так же, как я отложил оценку в моем примере выше. Это заставляет приложение работать в вашем вопросе. – dyp

ответ

0

Я понял, что следующий подход решает мою проблему.

#include <iostream> 
struct empty_ {}; 

template<class derT> 
struct A 
{ 
    A(derT * ptr) : m_ptr(ptr) {} 
    // 
    template<class T=empty_> 
    void func() { m_ptr->f(); } 
private: 
    derT *m_ptr; 
}; 

struct B : public A<B> 
{ 
    B() : A<B>(this) {} 
    void f() { std::cout << "B::f\n"; } 
}; 

struct C : public A<C> 
{ 
    C() : A<C>(this) {} 
    void g() { std::cout << "C::g\n"; } 
}; 

int main() 
{ 
    B b; 
    C c; 
    b.func(); 
    c.g(); 
    // Does not compile (as disired) since class C does not have a function f() 
    //c.func(); 
} 

Это работает, потому что функция func является функцией шаблона, так что SFINAE заботится о функциональности enable_if.