0

my problem is similar to - Template function accepting any type similar to map<X, Y> - yet, it didn't solve it, because I'm using already templated object.

typedef struct _foo
{
    int x, y, z;
} Foo;

// Note - it cannot be specialized for CBufferInt, CBufferFloat
// because it holds additional informations, left them on purpose
template <class T>
struct CBuffer
{
public:
    T value;
    UINT8* ptr = nullptr;
    ComPtr<ID3D12Resource> resource = NULL;
};

I want to call function like this:

template <typename T>
void TemplateFunction(CBuffer<T> cb);

int main()
{
   CBuffer<Foo> cb;
   TemplateFunction<Foo>(cb);
}

I've tried multiple configurations:

template <typename T> void TemplateFunction(CBuffer<T> cb);
template <typename T> void TemplateFunction(T cb);
template <template <typename> class CB, typename T> void TemplateFunction(CB<T> cb);

Is it possible to use template the way I desire (i.e. CBuffer) or do I have to create workaround?

Edit #1: Below code created in new class is working. I even went further and replaced CB and Foo with my own structures and it was working correctly.

#pragma once
#ifndef _TEST_STACK_OVERFLOW_H_
#define _TEST_STACK_OVERFLOW_H_

typedef struct _foo
{
public:
    XMFLOAT4 a;
    XMFLOAT3 b;
    XMFLOAT2 c;
} Foo;

template <class T>
struct CB
{
public:
    T value;
    UINT8* ptr = nullptr;
    ComPtr<ID3D12Resource> resource = NULL;
};

template <typename T>
void CreateRaytracingPipeline(CB<T> cb);

class TestStackOverflow
{
public:
    TestStackOverflow()
    {
        CB<Foo> cb{};
        CreateRaytracingPipeline(cb);
    }
};

#endif // !_TEST_STACK_OVERFLOW_H_

template<typename T>
inline void CreateRaytracingPipeline(CB<T> cb)
{
}

However in my final code, I am having this error message:

Error   LNK2019 unresolved external symbol "public: void __cdecl RaytracingResources::CreateRaytracingPipeline<struct _sceneConstantBuffer>(struct CBuffer<struct _sceneConstantBuffer>)" (??$CreateRaytracingPipeline@U_sceneConstantBuffer@@@RaytracingResources@@QEAAXU?$CBuffer@U_sceneConstantBuffer@@@@@Z) referenced in function WinMain RTCP    C:\Users\Kamil\Documents\_Projects\RTCP\RTCP\RTCP.obj   1   

In this commit, I am providing source code, which is only calling function in question and instantly closes executable instance - https://github.com/komilll/RTCP/tree/3d0b0858420734f7f16c92e7d608b2f19e01d17c Please relate to RTCP.cpp which constists only of code below:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow)
{
    HRESULT result = S_OK;

    CBuffer<SceneConstantBuffer> cb{};
    RaytracingResources* raytracing = new RaytracingResources();
    raytracing->CreateRaytracingPipeline(cb);

    return 0;
}

Where CBuffer is:

template <class T>
struct CBuffer
{
public:
    T value;
    UINT8* ptr = nullptr;
    ComPtr<ID3D12Resource> resource = NULL;
};

SceneConstantBuffer is:

typedef struct _sceneConstantBuffer
{
    XMMATRIX projectionToWorld;
    XMFLOAT4 cameraPosition;
    XMFLOAT4 lightPosition;
    XMFLOAT4 lightAmbientColor;
    XMFLOAT4 lightDiffuseColor;
} SceneConstantBuffer;

RaytracingResources is:

class RaytracingResources
{
public:
    RaytracingResources() = default;

    template <typename T>
    void CreateRaytracingPipeline(CBuffer<T> cb);
}
template<typename T>
inline void CreateRaytracingPipeline(CBuffer<T> cb)
{

}
  • What errors are you getting? Apart from missing the body of `TemplateFunction` what you have [should work](http://coliru.stacked-crooked.com/a/407647f721dad7d5) – Caleth Aug 10 '20 at 12:42
  • 2
    Can we get a [mre]? The code as shown should work – NathanOliver Aug 10 '20 at 12:42
  • 2
    Aside: `typedef struct _foo { ... } Foo;` can be simplified to `struct Foo { ... };` in C++ – Caleth Aug 10 '20 at 12:46
  • I filled missing information about minimal reproducible example @NathanOliver – DirectX_Programmer Aug 10 '20 at 15:17
  • @Caleth I've added error message. Can you tell me or relate to source, what's the difference between typedef struct and struct? I've noticed multiple times that typedef code is being used in Graphics programming field code. – DirectX_Programmer Aug 10 '20 at 15:18
  • Looks like the link is unable to find the implementation of `CreateRaytracingPipeline`. – Asesh Aug 10 '20 at 15:29
  • You are missing an implementation of `RaytracingResources::CreateRaytracingPipeline(...)`, i.e. the a class funciton/method. The implementation you provide is for a function called `CreateRaytracingPipeline(...)`, which resides in global scope, and not in the `RaytracingResources`-class scope. – Banan Aug 11 '20 at 11:59
  • @Banan I was trying method described by you and it isn't working. Please relate to my answer, why this cannot work (links at the bottom). – DirectX_Programmer Aug 12 '20 at 13:28
  • @DirectX_Programmer I have made an example from different bits an pieces of your post: [https://godbolt.org/z/3EYzaT](https://godbolt.org/z/3EYzaT). – Banan Aug 15 '20 at 11:59

1 Answers1

0

Thanks @Asesh for suggestion, it helped me "solve" this problem (I have too low rep to give upvotes :< ).

The way that worked for me was:

class RaytracingResources
{
public:
    RaytracingResources() = default;
}
template<typename T>
inline void CreateRaytracingPipeline(CBuffer<T> cb)
{

}

When I was trying to declare template inside class in *.h and defining template inside class in *.cpp, it wasn't working.

Other way it worked, was directly defining template inside class in *.cpp without creating declaration i.e.

class RaytracingResources
{
public:
    RaytracingResources() = default;
    template<typename T>
    inline void CreateRaytracingPipeline(CBuffer<T> cb)
    {

    }
}

Thanks for help from everyone who contributed in this thread. If anybody is willing to explaine, why declaration in header and definition in class implementation is failing to link, I will be grateful.

Edit:

I think that below resources are explaining problem enough for anyone seeking answer: