0

I have two modules that I have separated out into two different .h and .cpp files. I would like to have both modules be declared in the same namespace, but I receive the error candidate found by name lookup is 'my_namespace' and error: reference to 'my_namespace' is ambiguous. Why is this the case?

I have listed below my cmake config, the two header files and the module_b source file.

file(
    GLOB HEADER_LIST CONFIGURE_DEPENDS 
    "${myproj_SOURCE_DIR}/include/myproj/*.h"
)

# Make an automatic library - will be static or dynamic based on user setting
add_library(
    ${CMAKE_PROJECT_NAME}
    module_a.cpp
    module_b.cpp
    ${HEADER_LIST}
)

target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ../include)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ./)

# All users of this library will need at least C++17
target_compile_features(${CMAKE_PROJECT_NAME} PUBLIC cxx_std_17)

// module_a.h
namespace my_namespace { // << note: candidate found by name lookup is 'my_namespace'
    struct My_Struct_A {
        int a;
    };
}
// module_b.h
#include <my_proj/module_a.h>

namespace my_namespace { // << note: candidate found by name lookup is 'my_namespace'
    struct My_Struct_B {
        int b;
        My_Struct_A ab;
    };

    My_Struct_B do_something();
}
// module_b.cpp
#include <my_proj/module_b.h>

my_namespace::My_Struct_B my_namespace::do_something() { // << error: reference to 'my_namespace' is ambiguous
    return My_Struct_B { 1, { 2 } };
}

JustKash
  • 687
  • 2
  • 13
  • 28
  • Are these "modules" in the sense of software subcomponents, or in the sense of C++20 "modules"? It looks like the former, but if you were trying to do the latter you might get multiple distinct namespaces. – Ben Voigt Mar 26 '21 at 18:33
  • Does the error occur only when using cmake, or also when writing the compile command-line out manually? – Ben Voigt Mar 26 '21 at 18:36
  • Note that you can probably work around your problem by writing `::my_namespace::do_something` – Ben Voigt Mar 26 '21 at 18:37
  • @BenVoigt sorry this is just software modules; I am using c++17. I've actually not tried it without CMake, but CMake just uses the regular compilation steps, so I didn't think it'd matter. Also adding the global resolution identifier before the namespace doesn't help. – JustKash Mar 26 '21 at 18:41
  • 1
    Clean compile (with one I assume typo fixed) - https://godbolt.org/z/976M3rdd5 – Richard Critten Mar 26 '21 at 18:42
  • @RichardCritten It's weird, it seems to only be a problem when separated into different `.h` files. – JustKash Mar 26 '21 at 18:43
  • #include does a file merge (literally includes) is there anything you have edit out to make the question shorter like a `using namesspace` ? – Richard Critten Mar 26 '21 at 18:44
  • @RichardCritten Yes, I thought this is very unusual. I am not using any `using` directives. – JustKash Mar 26 '21 at 18:54
  • I am not too familiar with `cmake`, but [the documentation](https://cmake.org/cmake/help/latest/command/add_library.html) indicates that you are supposed to put the source in the `add_library()` function and source does not usually include the header files. Is there a way to spit out the compiler calls that `cmake` runs? – clcto Mar 26 '21 at 19:11
  • i.e. What happens if you remove the `${HEADER_LIST}`? – clcto Mar 26 '21 at 19:18
  • @clcto removing `${HEADER_LIST}` didn't change anything. – JustKash Mar 26 '21 at 20:00
  • @BenVoigt it seems to work fine when I run `g++ -std=c++17 *.cpp`, so it's definitely something with how CMake is doing things. – JustKash Mar 26 '21 at 20:36
  • @JustKash Does cmake show you the command line it is trying to run? Maybe if you add a `-v` for verbosity? – Ben Voigt Mar 26 '21 at 20:58
  • Looks like [you want `set(CMAKE_VERBOSE_MAKEFILE on)`](https://stackoverflow.com/questions/4808303/making-cmake-print-commands-before-executing) to help with debugging... – Ben Voigt Mar 26 '21 at 21:00
  • @BenVoigt I added verbose output, but didn't see anything interesting. – JustKash Mar 26 '21 at 22:13
  • Didn't it give you the g++ command line it was running, right before g++ gave an error? Do you also get an error if you use that *exact* g++ command? If the g++ command used by cmake fails and `g++ -std=c++17 *.cpp` works, then edit the exact `g++` command runs into your question, maybe the problem will jump out at someone. – Ben Voigt Mar 26 '21 at 22:31
  • @BenVoigt, I made a simpler representative project to test and it works! So, now I am just trying to figure out the difference; I will update the question with the solution. – JustKash Mar 26 '21 at 22:41
  • @BenVoigt All I did was change the name of the namespace from a 3 letter word to a 6 letter word and it worked. No idea. – JustKash Mar 27 '21 at 21:45

1 Answers1

2

The return value, My_Struct_B, is declared within my_namespace so you need to qualify it as such:

my_namespace::My_Struct_B my_namespace::do_something() {
    return My_Struct_B { 1, { 2 } };
}

The error message is technically correct but a bit misleading.

Alternatively (thanks @Eljay):

namespace my_namespace {

My_Struct_B do_something() {
    return My_Struct_B { 1, { 2 } };
}

}
Woodford
  • 3,746
  • 1
  • 15
  • 29
  • Although I do it this way myself, I acknowledge that this is one of the reasons to do the definitions within the namespace, rather than qualifying the definition into the namespace. – Eljay Mar 26 '21 at 18:45
  • That was just a typo on my part; I did have the resolution qualifier on the return type, the error is still there. – JustKash Mar 26 '21 at 18:55
  • Another option is trailing return type: `auto my_namespace::do_something() -> My_Struct_B { ... }` Within the definition of `do_something`, the namespace is in scope. – Ben Voigt Mar 26 '21 at 20:57