#include <iostream>
#include <memory>

struct A {
	A() {
		std::cout << "Constructor" << std::endl;
	}
	A(const A&) noexcept {
		std::cout << "Copy constructor" << std::endl;
	}
	A(A&&) noexcept {
		std::cout << "Move constructor" << std::endl;
	}
};

struct onlyMovable {
	onlyMovable() = default;
	onlyMovable(onlyMovable&&) = default;
	onlyMovable(const onlyMovable&) = delete; // Запрещаем копирование объекта
};

struct B {
	B(A) {}
	B(onlyMovable) {}
};

template <typename T, typename... Args>
std::shared_ptr<T>
factory1(Args... args)                                       
{
    return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
}

template <typename T, typename... Args>
std::shared_ptr<T>
factory2(Args... args)                                       
{
    return std::shared_ptr<T>(new T(args...));
}
 
int main() {
	
	std::cout << "---------------------------------" << std::endl;
	std::cout << "With std::forward" << std::endl;
	auto p1 = factory1<B>(A());
	std::cout << "---------------------------------" << std::endl;
	std::cout << "Without std::forward" << std::endl;
	auto p2 = factory2<B>(A());
	std::cout << "---------------------------------" << std::endl;

	
	auto p3 = factory1<B>(onlyMovable()); 
	//auto p4 = factory2<B>(onlyMovable()); // Ошибка компиляции, копировать этот объект нельзя
}