0

I have this following C++ code:

#include <Windows.h>
#include <type_traits>

class Sample
{
    decltype(&ActivateActCtx) ActivateActCtx;
    decltype(&ReadFile) ReadFile;
    decltype(&WriteFile) WriteFile;

    template <typename F>
    static void ResolveFunction(F& output, const char* name)
    {
        static auto handle{ GetModuleHandleW(L"kernel32.dll") };
        if (!((output = reinterpret_cast<F>(GetProcAddress(handle, name)))))
            throw name;
    }

public:

    Sample()
    {
        ResolveFunction(ActivateActCtx, "ActivateActCtx");
        ResolveFunction(ReadFile, "ReadFile");
        ResolveFunction(WriteFile, "WriteFile");
    }

    template <typename T>
    constexpr T Get()
    {
        if constexpr (std::is_same_v < T, decltype(&::ReadFile)>)
            return ReadFile;
        if constexpr (std::is_same_v < T, decltype(&::WriteFile)>)
            return WriteFile;
        if constexpr (std::is_same_v < T, decltype(&::ActivateActCtx)>)
            return ActivateActCtx;

        return {};
    }
};

int main()
{
    Sample s;
    s.Get<decltype(&ReadFile)>()(nullptr, nullptr, 0, nullptr, nullptr);
    s.Get<decltype(&WriteFile)>()(nullptr, nullptr, 0, nullptr, nullptr);
    s.Get<decltype(&ActivateActCtx)>()(nullptr, nullptr);

    return 0;
}

As you can see auto handle{ GetModuleHandleW(L"kernel32.dll") }; is static and should be assigned with the return value of GetModuleHandleW just once. However, upon disassembly of the program it seems to be assigned three times, for each call in the constructor. I know that an implicit inline is before ResolveFunction, but I don't think that should literally inline so aggressively so that the definition of static is violated.

enter image description here

enter image description here

I am using Microsoft Visual C++ 19.32.31329. Optimization settings: /O2 /Oi /GL I also tried maximum optimization for size and got the same result. Everything is compiled as Release of course.

Arush Agarampur
  • 1,340
  • 7
  • 20
  • 1
    Each call to `ResolveFunction` is with a different type, so a different instantiation of the template. `static` local var are unique to each instance of a template function, even if the variable's own type isn't templated. – Peter Cordes Jul 28 '22 at 00:09
  • 2
    I always found that using the proper terminology _function template_ (instead of _template function_), helps to clarify expectations of behavior. It _generates_ a new function for each type based on the function template. – paddy Jul 28 '22 at 00:13

0 Answers0