1

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

Spikie
  • 389
  • 2
  • 8
  • 21
  • Please copy-paste the full and complete build log *as text* into your question. [Don't post images of errors, code or data](https://meta.stackoverflow.com/questions/285551/why-should-i-not-upload-images-of-code-data-errors). And of course, please try to create a [mre] to show us. – Some programmer dude Jun 07 '23 at 08:21
  • `bool Plugin::API::operator<` -> `bool Plugin::API::Adapter::operator<` – Mike Vine Jun 07 '23 at 08:28
  • @MikeVine Friends are not members. – molbdnilo Jun 07 '23 at 08:31
  • minimal reproducible example !! – Spikie Jun 07 '23 at 09:01
  • https://github.com/obsproject/obs-amd-encoder/blob/master/source/api-base.cpp – Spikie Jun 07 '23 at 09:12
  • @ molbdnilo friend are not members please what are they ? – Spikie Jun 07 '23 at 09:13
  • C++ cannot be learned by trial and error + internet searches. Invest in a few [good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list#388282), spend some months reading and playing with toy programs, then gradually move on to real stuff. In my experience, C++ usually takes 2-3 years to get comfortable with (with daily study and practice) and at least 5+ years to master. – Jesper Juhl Jun 07 '23 at 10:06
  • yea ok have to start from somewhere ! books ok please recommd one ! i have been writing python codes for 18 years – Spikie Jun 07 '23 at 12:24

2 Answers2

4

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.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • You need to declare them as friends with the fully qualified names please i need to see example . i am very new to c++ – Spikie Jun 07 '23 at 09:20
  • Unqualified friend declarations certainly do put things in the smallest enclosing namespace; isn’t the issue here that one is trying to define them as if they are **class** members? – Davis Herring Jun 18 '23 at 18:20
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

viraltaco_
  • 814
  • 5
  • 14
  • thanks for your answer but unfornuately when i effected the changes you recommends i have Severity Code Description Project File Line Source Suppression State Tool Error (active) E0344 too many parameters for this operator function enc-amf-test C:\Users\cino\Documents\softwares\OBS\obs\plugins\enc-amf\include\api-base.hpp 53 IntelliSense Visual C++ IntelliSense – Spikie Jun 20 '23 at 07:08