2017-10-29 6 views
3

Vulkanを学んでいるうちに、VulkanCookbookにいくつかのコードがあります。 VulkanCookbookでは、Vulkan関数とクラスを手作業でインポートするコードを記述しています。まあ、私はゆっくりとVulkanのLunarGのSDKに変換してきましたが、64ビットVkFenceではVkFence_T *に問題が出てきましたが、これは32ビットではすべてtypedefされていますが、uint64_tとしてtypedefを使用したテンプレートの特殊化

#include <iostream> 
#include <stdint.h> 

typedef uint64_t A; 
typedef uint64_t B; 

template<typename T> 
class Handler 
{ 
    void DestroyObject(T parent); 
}; 

template<> 
inline void Handler<A>::DestroyObject(A object) { 
    std::cout << "destroy type A" << std::endl; 
} 

template<> 
inline void Handler<B>::DestroyObject(B object) { 
    std::cout << "destroy type B!" << std::endl; 
} 

int main() 
{} 

以下のようなコードを使用していますVkDestroyerにとっての問題は、この問題に対処するために何か良い方法はありか、私は手でオブジェクトを削除するには、すべてのサンプルコードを移動して、手直ししなければなりませんか?可能であれば私は32ビットでコンパイルしたいと思います。

申し訳ありませんこの質問が他に尋ねられた場合、私はGoogleがいつも部分的なテンプレートや他の非関連のトピックになってしまったので、それを見つけることができませんでした。そして、私はコンパイラが_Aと_Bを見ているコードの問題を理解していますが、別の名前が付けられていることを気にせずに、uint64_tを処理するだけで、DestroyObjectオーバーロードが再定義エラーを引き起こす同じテンプレートタイプになります。

編集:実際にコアの問題ではないので、無効な命名を使用してコードを修正しました。

+0

@StoryTeller(a)は、この問題を回避するためにとにかく存在しますか? (b)私がテストしていたコードで、そのコードの古いバージョンを誤って貼り付けたことを変更しました。 – Cieric

+0

タイプは完全に一体化されていますか? – StoryTeller

+0

@StoryTellerはい、20のようなものがあります。彼らがどのように動作するかに基づいて、私は32ビットモードで64ビットポインタのように使用されていると思います。 – Cieric

答えて

3

C++には強力なtypedefがありません。型エイリアスは、既存の型の単なる別の名前であり、使用時にエイリアスと完全に同じです。

AおよびBは、両方ともuint64_tとの関係にあるエイリアスではなく、実際のタイプである必要があります。一体型に制約されている限り、それらの中から新しいものを構築することができます。

ソリューションは、基になる型が指定された列挙体です。このような

#include <type_traits> 

template<typename E> 
using argument_t = std::conditional_t<std::is_enum<E>::value, 
             std::underlying_type_t<E>, 
             E>; 

template<typename T> 
class Handler 
{ 
    void DestroyObject(argument_t<T> parent); 
}; 

enum A : uint64_t {}; 
enum B : uint64_t {}; 

template<> 
inline void Handler<A>::DestroyObject(uint64_t object) { 
    std::cout << "destroy type A" << std::endl; 
} 

template<> 
inline void Handler<B>::DestroyObject(uint64_t object) { 
    std::cout << "destroy type B!" << std::endl; 
} 

上記作品:

  • argument_tユーティリティをチェックEが列挙され、そしてそれのための基になる型を与える場合。それ以外の場合は、Eに戻ります。

  • プライマリテンプレートはTを受け入れ、必要に応じて引数を変換します。

  • ABとなりますので、それぞれタイプにすることができます。この関数は、基になる型をパラメータとして受け取ります。

+0

この解決策は実際には本当に素晴らしいですが、彼らがライブラリに含まれているヘッダーの一部分であるので、タイプAとタイプBは私の場合は実行可能です。しかし、あなたの回答が質問に答えると、私はそれを正しいものとしてマークし、問題が存在しないところで64ビットでコンパイルを続けます。 – Cieric

0

あなたはほぼそうです。上記の関数Handler<_A>::DestroyObject(_A object)Handler<_B>::DestroyObject(_B object)は実際にはテンプレートメンバー関数の具体的なインスタンス化です。作者はこの関数の汎用バージョンを提供していないため、uint32_tを使用してクラスをインスタンス化しようとする際に問題が発生しています。簡単な修正は、template<> void Handler<uint32_t>::DestroyObject(uint32_t o)関数を記述することです。より多くの文脈がなければ、私はより良いアドバイスを提供することはできません。

+0

問題は、typedef AとBは同じコアタイプですが、コアタイプではなくtypedefタイプに基づいて実行するには、別のコードが必要です。そして、 'template <> void Handler :: DestroyObject(uint32_t o)'は、渡された型に基づいて結果のコードが異なる必要があるため、機能しません。 – Cieric

0

型パラメータとしてABをpasdedさを区別するためのテンプレートのための方法はありません。

手動でオブジェクトをクリーンアップする方法がありますが、問題があまりにも曖昧で、問題が本当に何であるかを判断するために実行可能ではないソリジションを取得する方法を見つけることに集中しています。

おそらく、タイプ自体と異なるものを使用してタイプ間の区別をはずす必要があります。

+0

Vulkanの使い方を実際に学びたいので、コードを大きく変更したくないのは主に気にしませんでしたが、問題があるので64ビットでコンパイルを続けます。 – Cieric

関連する問題