#c #templates #parameters
Вопрос:
Я знаю некоторые коды, которые могут определить, есть ли у класса функция-член, как показано ниже
#include <iostream>
#include <type_traits>
#include <string>
using namespace std;
template<typename T, typename F>
constexpr auto has_member_impl(Famp;amp; f) -> decltype(f(std::declval<T>()), true) { return true; }
template<typename>
constexpr bool has_member_impl(...) { return false; }
#define has_member(T, EXPR) has_member_impl<T>( [](autoamp;amp; obj)->decltype(obj.EXPR){} )
class A{
public:
void operator()(int data){ cout << data << endl; }
};
class B{
public:
template <class CLASS>
void func_int(CLASS amp;c, int data){
if constexpr(has_member(CLASS, operator()(int()))) c(data);
}
template <class CLASS>
void func_string(CLASS amp;c, std::string data){
if constexpr(has_member(CLASS, operator()(std::string()))) c(data);
}
};
int main(){
A a;
B b;
b.func_int(a, 1); // print out 1
b.func_string(a, "2"); // print out nothing, unless class 'A' defines 'operator()(string);'
}
где,
- класс A содержит функцию-член ‘operator()’
- в классе B функции «func_int» и «func_string» используют constexpr(has_member(…)) для определения, существуют ли в КЛАССЕ соответственно «оператор()(int)» и » оператор()(std::строка)». Если да, выполните эту функцию.
Когда функция-член класса A является шаблонной функцией, код может быть примерно таким, как показано ниже,
class A{
public:
template <typename T>
void operator()(T data){ cout << data << endl; }
};
class B{
public:
template <class CLASS, typename DATA>
void func(CLASS amp;c, DATA data){
if constexpr(has_member(CLASS, operator()(1))) c(data);
}
};
int main(){
A a;
B b;
b.func(a, 1); // print out 1
b.func(a, "2"); // print out 2
}
где часть оператора constexpr изменяется на » оператор()(1)».
На этот раз я хочу сделать его более сложным, как показано ниже
class A{
public:
template <typename T>
void operator()(T data1, T data2){ cout << data1 << ' ' << data2 << endl; }
};
class B{
public:
template <class CLASS, typename DATA>
void func(CLASS amp;c, DATA data1, DATA data2){
if constexpr(has_member(CLASS, operator()(1, 2))) c(data1, data2);
}
};
int main(){
A a;
B b;
b.func(a, 1, 2); // print out '1 2'
b.func(a, 1, "2"); // print out '1 2' (I want to make it print out nothing)
}
где,
- в классе A функция ‘operator()’ принимает два параметра одного и того же типа
- похоже,что состояние constexpr в классе B может использовать любой аргумент ‘operator()(x, y)’ для обнаружения его существования, независимо от того, относятся ли два параметра к одному и тому же типу
Я хочу знать, что » когда функция A является шаблонной функцией, как определить, имеют ли два параметра один и тот же тип?‘
Комментарии:
1. Ваши первые примеры проверяют, работает ли конкретный код, вызывающий функцию-член. Они не обнаруживают, существует ли функция-член. В этом есть тонкая разница. Без размышлений можно проводить только тесты утиного типа. Поэтому вам нужно сформулировать свое требование с точки зрения операций типа утки
2.
1,2
жестко закодированы, как насчетtemplate <class CLASS, typename DATA> void func(CLASS amp;c, DATA data1, DATA data2){ if constexpr(std::is_invocable_v<CLASS, DATA, DATA>)) c(data1, data2); }
?3. @Jarod42 довольно полезно. Спасибо.