Проблема (1) и (2) - это разные проблемы.
Проблема (1) проистекает из того факта, что в следующем std::is_invocable_v
template<typename T,
typename ... Args>
void print(T&& t, Args&& ... args)
{
if constexpr (std::is_invocable_v<decltype(&T::display),T*,Args...>)
// no T but std::decay_t<T> ...............^...........^
вместо T
(это может быть ссылка) вам нужен «распавшийся» тип
Я предлагаю
template <typename T, typename ... Args>
void print (T && t, Args && ... args)
{
using U = std::decay_t<T>;
if constexpr ( std::is_invocable_v<decltype(&U::display), U*, Args...> )
t.display(std::forward<Args>(args)...);
else
std::cout << "not applicable !" << std::endl;
}
Проблема (2) возникает из-за того, что объяснение параметров шаблона в следующем print()
Позвоните
template <typename... Args>
void run(Args&& ... args)
{
print<T,Args...>(t_,std::forward<Args>(args)...);
}
, чтобы помешать правильному выводу шаблона.
Предложение: пусть вывод шаблона и совершенная пересылка работают и вызывают функцию следующим образом
print(t_,std::forward<Args>(args)...);