skip to Main Content

Question Edited
Hello I am new to c++ code . just getting my toes wet. I am learning C++. I picked OBS Studio because it is the coolest C++ i can find. i got the cmake to configure and generate 55 Microsoft visual studio community edition running on Windows 11

The project that is actually thorwing the error is
A Plugin that integrates the AMD AMF encoder into OBS Studio

I have since learn enough C plus plus to understand how to ask the question clear enough i guess.What i found out

The Error is
Error C2039 ‘<‘: is not a member of ‘Plugin::API’ enc-amf-test

The part of the code throw the error is adapter pattern doing c++ operator overload .

The implementation code can not refer the declaration code in the header file as it will require full namespace paths

My Question
My thought is the operator which is already declared in the header file. why i am get the above error message yet have this error as Error C2593 ‘operator <‘ is ambiguous

api-base.hpp

   /*
 * A Plugin that integrates the AMD AMF encoder into OBS Studio
 * Copyright (C) 2016 - 2018 Michael Fabian Dirks
 *
 
 */

#pragma once
#include <map>
#include <memory>
#include <string.h>
#include <vector>
#include "plugin.hpp"

namespace Plugin {
    namespace API {
        enum class Type : uint8_t {
            Host,
            Direct3D9,
            Direct3D11,
            OpenGL,
        };

        // An Adapter on an API
        struct Adapter {
            int32_t     idLow, idHigh;
            std::string Name;

            Adapter() : idLow(0), idHigh(0), Name("Invalid Device") {}
            Adapter(const int32_t p_idLow, const int32_t p_idHigh, const std::string& p_Name)
                : idLow(p_idLow), idHigh(p_idHigh), Name(p_Name){}

            Adapter(Adapter const& o) : Name(o.Name), idLow(o.idLow), idHigh(o.idHigh) {}
            void operator=(Adapter const& o)
            {
                idLow  = o.idLow;
                idHigh = o.idHigh;
                Name   = o.Name;
            }

            friend bool operator <(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
            friend bool operator >(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
            friend bool operator <=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
            friend bool operator >=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);

            friend bool operator ==(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
            friend bool operator !=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right);
        };

        // Instance of an API Adapter
        struct Instance {
            public:
            Instance();
            virtual ~Instance();

            virtual Adapter GetAdapter() = 0;
            virtual void*   GetContext() = 0;
        };

        // API Interface
        class IAPI {
            public:
            IAPI();
            virtual ~IAPI();

            virtual std::string GetName() = 0;
            virtual Type        GetType() = 0;

            virtual std::vector<Adapter> EnumerateAdapters() = 0;
            Adapter                      GetAdapterById(const int32_t idLow, const int32_t idHigh);

            Adapter                      GetAdapterByName(const std::string& name);

            virtual std::shared_ptr<Instance> CreateInstance(Adapter adapter) = 0;
        };

        // Static API Stuff
        void                               InitializeAPIs();
        void                               FinalizeAPIs();
        size_t                             CountAPIs();
        std::string                        GetAPIName(size_t index);
        std::shared_ptr<IAPI>              GetAPI(size_t index);
        std::shared_ptr<IAPI>              GetAPI(const std::string& name);
        std::shared_ptr<IAPI>              GetAPI(Type type);
        std::vector<std::shared_ptr<IAPI>> EnumerateAPIs();
        std::vector<std::string>           EnumerateAPINames();
    } // namespace API
} // namespace Plugin

api-base.cpp

#include "api-base.hpp"
#include <cinttypes>
#include "api-d3d11.hpp"
#include "api-d3d9.hpp"
#include "api-host.hpp"
#include "api-opengl.hpp"

#if defined(_WIN32) || defined(_WIN64)
extern "C" {
#include <VersionHelpers.h>
#include <windows.h>
}
#endif

using namespace Plugin::API;

// An Adapter on an API
bool Plugin::API::operator< (const Plugin::API::Adapter& left, const Plugin::API::Adapter& right)
{
    if (left == right)
        return left.Name < right.Name;
    else
        return (((uint64_t)left.idLow + ((uint64_t)left.idHigh << 32))
                < ((uint64_t)right.idLow + ((uint64_t)right.idHigh << 32)));
}

bool Plugin::API::operator >(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right)
{
    return right < left;
}

bool Plugin::API::operator<=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right)
{
    return !(right < left);
}

bool Plugin::API::operator >=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right)
{
    return !(left < right);
}

bool Plugin::API::operator==(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right)
{
    return ((left.idLow == right.idLow) && (right.idHigh == right.idHigh));
}

bool Plugin::API::operator !=(const Plugin::API::Adapter& left, const Plugin::API::Adapter& right)
{
    return !(left == right);
}

// Instance of an API Adapter
Plugin::API::Instance::Instance() {}

Plugin::API::Instance::~Instance() {}

// API Interface
Plugin::API::IAPI::IAPI() {}

Plugin::API::IAPI::~IAPI() {}

Plugin::API::Adapter Plugin::API::IAPI::GetAdapterById(const int32_t idLow, const int32_t idHigh)
{
    for (auto adapter : EnumerateAdapters()) {
        if ((adapter.idLow == idLow) && (adapter.idHigh == idHigh))
            return adapter;
    }
    return *(EnumerateAdapters().begin());
}

Plugin::API::Adapter Plugin::API::IAPI::GetAdapterByName(const std::string& name)
{
    for (auto adapter : EnumerateAdapters()) {
        if (adapter.Name == name)
            return adapter;
    }
    return *(EnumerateAdapters().begin());
}

// Static API Stuff
static std::vector<std::shared_ptr<IAPI>> s_APIInstances;
void                                      Plugin::API::InitializeAPIs()
{
#ifdef _WIN32
    if (IsWindows8OrGreater()) {
        // DirectX 11
        try {
            s_APIInstances.insert(s_APIInstances.end(), std::make_shared<Direct3D11>());
        } catch (const std::exception& PLOG_VAR(ex)) {
            PLOG_WARNING("Direct3D 11 is not supported due to error: %s", ex.what());
        } catch (...) {
            PLOG_WARNING("Direct3D 11 not supported.");
        }
    } else if (IsWindowsXPOrGreater()) {
        // Direct3D 9
        try {
            s_APIInstances.insert(s_APIInstances.end(), std::make_shared<Direct3D9>());
        } catch (const std::exception& PLOG_VAR(ex)) {
            PLOG_WARNING("Direct3D 9 is not supported due to error: %s", ex.what());
        } catch (...) {
            PLOG_WARNING("Direct3D 9 not supported.");
        }
    }
#endif

    // Mikhail says these are for compatibility only, not actually backends.
    //// OpenGL
    //{
    //  s_APIInstances.insert(s_APIInstances.end(), std::make_shared<OpenGL>());
    //}

    //// Host
    //{
    //  s_APIInstances.insert(s_APIInstances.end(), std::make_shared<Host>());
    //}
}

void Plugin::API::FinalizeAPIs()
{
    s_APIInstances.clear();
}

size_t Plugin::API::CountAPIs()
{
    return s_APIInstances.size();
}

std::string Plugin::API::GetAPIName(size_t index)
{
    if (index >= s_APIInstances.size())
        throw std::exception("Invalid API Index");

    return s_APIInstances[index].get()->GetName();
}

std::shared_ptr<IAPI> Plugin::API::GetAPI(size_t index)
{
    if (index >= s_APIInstances.size())
        throw std::exception("Invalid API Index");

    return s_APIInstances[index];
}

std::shared_ptr<IAPI> Plugin::API::GetAPI(const std::string& name)
{
    for (auto api : s_APIInstances) {
        if (name == api->GetName()) {
            return api;
        }
    }
    // If none was found, return the first one.
    return *s_APIInstances.begin();
}

std::shared_ptr<IAPI> Plugin::API::GetAPI(Type type)
{
    for (auto api : s_APIInstances) {
        if (type == api->GetType()) {
            return api;
        }
    }
    // If none was found, return the first one.
    return *s_APIInstances.begin();
}

std::vector<std::shared_ptr<IAPI>> Plugin::API::EnumerateAPIs()
{
    return std::vector<std::shared_ptr<IAPI>>(s_APIInstances);
}

std::vector<std::string> Plugin::API::EnumerateAPINames()
{
    std::vector<std::string> names;
    for (auto api : s_APIInstances) {
        names.push_back(api->GetName());
    }
    return names;
}

When I build these code in Visual Studio 2022 Community Version with clang Format on as if you look at the photo on the right the source of error say CL.

I get error
Error C2039 ‘<‘: is not a member of ‘Plugin::API’

![Text](https://stackoverfenter image description herelow.com/image.jpg)

Please Help Me

ok i am really to build OBS Studio from source

you find the code in this link
https://github.com/obsproject/obs-amd-encoder/blob/master/source/api-base.cpp

2

Answers


  1. Unqualified friend declarations declare the friends in the global namespace, not in the namespace of the enclosing class.

    You need to declare them as friends with the fully qualified names.’

    That is, not operator< but Plugin::API::operator<, just like when you define them.

    Login or Signup to reply.
  2. bool Plugin::API::operator<(
    

    should be

    bool Plugin::API::Adaptor::operator <(
    

    and it shouldn’t be declared as friend in the struct Adaptor declaration.

    Like this

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search