Мне нужен простой способ утверждать внутри шаблона, что параметр шаблона реализует метод ( или один из его родительских классов ).Я читал библиотеку концептуальных проверок, но трудно найти простой пример для выполнения простых проверок, подобных этой.
Я пытался следить за другими сообщениями (например, этой и этот другой ), который я изменил, чтобы я мог сделать его универсальным для многих типов методов (в моем примере Foo (methodName) и has_foo (имя Checker), после правильной работы, будут обернуты в качестве аргументов макроса, так чтоон может использоваться для любого метода)
код, который у меня есть на данный момент, такой:
template <typename TypeToBeChecked, typename Sign>
class has_foo {
static_assert( false , "inside root declaration of " "has_foo" );
public:
static const bool result = false;
};
template <typename TypeToBeChecked , typename R>
class has_foo < TypeToBeChecked , R(void) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(void)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t> class Helper{};
template <typename U> static no deduce(U*, Helper<R (BaseMixin::*)(), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template <typename TypeToBeChecked , typename R , typename ARG1>
class has_foo< TypeToBeChecked , R(ARG1) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(ARG1)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(ARG1){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t> class Helper{};
template <typename U>
static no deduce(U*, Helper<R (BaseMixin::*)(ARG1), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template <typename TypeToBeChecked , typename R , typename ARG1 , typename ARG2>
class has_foo< TypeToBeChecked , R(ARG1, ARG2) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(ARG1 , ARG2)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(ARG1,ARG2){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t>
class Helper{};
template <typename U>
static no deduce(U*, Helper<R (BaseMixin::*)(ARG1,ARG2), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template< typename Type >
struct Connector
{
static_assert( has_foo< Type , int(int, double) >::result , "Type has no Foo method" );
void Operate() {
Type t;
t.Foo(3);
}
};
struct Bla1 { int Foo(double f) { return (int)f; } };
struct Bla2 { int Foo(int g, double h) { return g+(int)h;} };
int main()
{
//Connector< Bla1 > a;
Connector< Bla2 > b;
};
Когда я компилирую этот пример кода (g ++ 4.4.3 ubuntu с -std =опция c ++ 0x, поэтому static_assert распознается) я получаю следующее:
$ g++ test.cpp -std=c++0x -o test
test.cpp:72: error: static assertion failed: "inside root declaration of has_foo"
test.cpp:79: error: static assertion failed: "inside specialization of has_foo for R(void)"
test.cpp:93: error: static assertion failed: "inside specialization of has_foo for R(ARG1)"
test.cpp:108: error: static assertion failed: "inside specialization of has_foo for R(ARG1 , ARG2)"
подождите прямо сейчас (обратите внимание, что Connector a прокомментирован) мой первый вопрос:
1) Правильно ли я предположить, что если утверждение оценивается, то содержащий шаблон создается?
РЕДАКТИРОВАТЬ: ответил GMan: static_assert оценивается во время синтаксического анализа, а не при создании экземпляра шаблона.Замена false на sizeof (TypeToBeChecked) == 0 делает его связанным со временем компиляции
2) Правильно ли я предположить, что, поскольку статическое утверждение в классе шаблона Connector создает экземпляр has_foo с подписью int (int, double), тогда НЕ нужно создавать экземпляры специализаций с одним параметром и без параметров?что не так с моими предположениями?
РЕДАКТИРОВАТЬ: это предположение верно, но теперь, когда я исправил в соответствии с 1) ответом, процесс создания экземпляров теперь ведет себя как ожидалось
3), если я раскомментирую Соединитель строка, я бы ожидал, что она потерпит неудачу (поскольку Bla1 имеет только Foo с единственной сигнатурой параметра. Однако это не так. Любая идея, что может быть не так? Особенно с учетом первого связанного сообщения