You are not logged in.

#1 2018-05-22 20:25:11

lnxsurf
Member
Registered: 2014-05-28
Posts: 68

C++ and Template Specialization

Hi,

I try to make a short hand for these vulkan calls:

// first example:
auto result {VK_INCOMPLETE};
std::vector<VkPhysicalDevice> devices {};
while (result == VK_INCOMPLETE) {
  uint32_t count {0};
  vkEnumeratePhysicalDevices(instance, &count, nullptr);
  devices.resize(count);
  result = vkEnumeratePhysicalDevices(instance, &count, devices.data());
}

// second
uint32_t count {0};
vkGetPhysicalDeviceQueueFamilyProperties(device, &count, nullptr);
QueueFamilies families {count};
vkGetPhysicalDeviceQueueFamilyProperties(device, &count, families.data());

In the second example, there are void functions and do not return a VkResult.

For the first example I wrote this:

template <
  typename Command,
  typename ExpectedResult
>
struct Query {
  VkResult result {VK_INCOMPLETE};
  Command &cmd;
		
  explicit Query(Command &command): cmd{command} {}
		
  template <class ... Args>
  const std::vector<ExpectedResult> operator()(Args&& ... args) {
    std::vector<ExpectedResult> items {};
    while (result == VK_INCOMPLETE) {
      uint32_t count {0};
      (*cmd)(std::forward<Args>(args)..., &count, nullptr);
      items.resize(count);
      result = (*cmd)(std::forward<Args>(args)..., &count, items.data());
    }
    return items;
  }
};

// usage:
Query<
  decltype(vkEnumeratePhysicalDevices),
  VkPhysicalDevice
> q {vkEnumeratePhysicalDevices};
		
Devices devices = q(instance);

I would like to define a partial specialization for Query where the specialization is any void function with any parameters to fit the second example.

Offline

#2 2018-06-28 19:16:10

lnxsurf
Member
Registered: 2014-05-28
Posts: 68

Re: C++ and Template Specialization

Here I found a solution...

	template <
		typename ReturnType,
		typename ExpectedResult
	>
	struct Callee;
	
	template <
		typename ExpectedResult
	>
	struct Callee<void, ExpectedResult> {
		const VkResult result = VK_SUCCESS;

		template <typename Command, class ... Args>
		auto operator()(const Command &cmd, Args&& ... args) const {
			std::vector<ExpectedResult> items {};
			uint32_t count {0};
			cmd(std::forward<Args>(args)..., &count, nullptr);
			items.resize(count);
			cmd(std::forward<Args>(args)..., &count, items.data());
			return items;
		}
	};

	template <
		typename ExpectedResult
	>
	struct Callee<VkResult, ExpectedResult> {
		VkResult result = VK_INCOMPLETE;
		
		template <typename Command, class ... Args>
		auto operator()(const Command &cmd, Args&& ... args) {
			std::vector<ExpectedResult> items {};
			while (result == VK_INCOMPLETE) {
				uint32_t count {0};
				cmd(std::forward<Args>(args)..., &count, nullptr);
				items.resize(count);
				result = cmd(std::forward<Args>(args)..., &count, items.data());
			}			
			return items;
		}
	};

	template <
		typename Command,
		typename ExpectedResult
	>
	struct Query {
		VkResult result;
		Command &cmd;
		
		explicit Query(Command &command): result{VK_INCOMPLETE}, cmd{command} {}
		
		template <class ... Args>
		const std::vector<ExpectedResult> operator()(Args&& ... args) {
			Callee< 
				decltype(cmd(std::forward<Args>(args)..., 0u, nullptr)), 
				ExpectedResult
			> callee {};
			
			auto items = callee(cmd, args...);
			result = callee.result;
			return items;
		}
	};

Offline

Board footer

Powered by FluxBB