Вы не получите ожидаемый результат, потому что тип данных First
в вашем Checker
функциональном объекте при вызове после std::bind()
имеет тип int&
, а не int
.
Следовательно, std::is_base_of<Base<B,int&>, B>
не создает std::true_type
для вызова Checker::check
.
Проблема в том, что std::bind
создает объект, который внутренне хранит аргументы для функции, которую вы ему передаете. Поэтому существует именованное l-значение в качестве нестатического члена-данных объекта, возвращаемого std::bind
, которое содержит значение, которое вы передали в качестве аргумента для привязки к вашей функции. Когда этот нестатический элемент данных затем передается в ссылку на r-значение во время вызова operator()
функтора, он передается как ссылка на l-значение, поскольку он больше не является временным объектом. У вас была бы похожая проблема, если бы вы сделали что-то вроде:
int x = 1;
Checker<B> ch2;
std::cout<<ch2(x, 3.14)<<std::endl;
Именованное значение x
является l-значением и будет передано аргументу first
в вашем методе operator()
как ссылка на l-значение, а не как временное, поскольку first
является r -значение ссылки. Следовательно, ваш тип снова будет иметь вид int&
, а не int
, и вы напечатаете значение 0
.
Чтобы исправить эту проблему, вы можете сделать что-то вроде:
template<typename First, typename ...Args>
result_type operator()(First&& first, Args&&... params)
{
if (std::is_reference<First>::value)
{
return check(std::is_base_of<Base<T, typename std::remove_reference<First>::type>, T>(),
std::forward<First>(first),
std::forward<Args>(params)...);
}
else
{
return check(std::is_base_of<Base<T,First>, T>(),
std::forward<First>(first),
std::forward<Args>(params)...);
}
}
Это исключит ссылочный тип объекта и даст вам нужные результаты.