Here's an example:
#define MAKE_IT_WORK false
namespace Bob { // Bob's project namespace
struct DeviceFrequency {};
extern void debugf(const char* fmt, ...);
} // namespace Bob
namespace SSN { // Super-Secret Namespace
namespace debugging {
extern int ssn_debug;
extern void debugf(const char* fmt, ...);
} // namespace debugging
} // namespace SSN
namespace SSN::signals { // Super-Secret Namespace, project signals
template<typename Coder> // In the example, this imports Bob's namespace
class Frequency {
public:
Frequency( void )
{ using namespace ::SSN::debugging; // Why isn't this enough??
using ::SSN::debugging::debugf; // Or this??
if( ssn_debug )
#if MAKE_IT_WORK
::SSN::debugging:: // How can a developer predict that this is needed??
#endif
debugf("Frequency(%p,%zd)::Frequency\n", this, sizeof(*this));
}
}; // class Frequency
} // namespace SSN::signals
struct Controller {
SSN::signals::Frequency<Bob::DeviceFrequency> bobcon;
Controller( void ) : bobcon() {}
}; // class Controller
In this example, Bob duplicates the debugf function because he doesn't want to have to bring the entire SSN namespace into his private one and doesn't want to be bothered with fully qualifying it every time he uses it.
The SSN developer didn't realize that a template could also import its namespace (until it happened), apparently bringing ADL lookup into play. Although ADL lookup states that using statements in namespace are ignored, why it comes into play at all doesn't make sense. It seems way too easy for one namespace to unintentionally pollute another, and way too hard to predict where this might someday occur in inline code.
It looks like (at least) whenever templates are used within a namespace, every namespace function reference must be fully qualified because when using templates you can't predict when a name conflict might otherwise occur. Is this correct? If so, is there any way to avoid all that extra name qualifier typing that seems to be required? Is this exposure limited to templates, or is all imported inline code somehow similarly vulnerable?
Compiling (Dirty.cpp) using gcc versions 10.2.0 and 10.2.1 (Red Hat 10.2.1-5), I got the following messages:
make dirty
c++ -o Dirty.o -c S/Dirty.cpp -D_CC_GCC -D_OS_BSD -D_HW_X86 -D_OS_LINUX -IS -IH -g -O3 -finline->functions -std=gnu++17 -Wall -Wextra -Wmissing-declarations -Wswitch-default -Werror
S/Dirty.cpp: In instantiation of ‘SSN::signals::Frequency<Coder>::Frequency() [with Coder = Bob::DeviceFrequency]’:
S/Dirty.cpp:146:32: required from here
S/Dirty.cpp:139:12: error: call of overloaded ‘debugf(const char [30], SSN::signals::Frequency<Bob::DeviceFrequency>*, long unsigned int)’ is ambiguous
139 | debugf("Frequency(%p,%zd)::Frequency\n", this, sizeof(*this));
| ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
S/Dirty.cpp:124:13: note: candidate: ‘void SSN::debugging::debugf(const char*, ...)’
124 | extern void debugf(const char* fmt, ...);
| ^~~~~~
S/Dirty.cpp:117:13: note: candidate: ‘void Bob::debugf(const char*, ...)’
117 | extern void debugf(const char* fmt, ...);
|
(Edited: The example has been restored to the original, now as reformatted by #1201ProgramAlarm. A modified version appears that tests examples follows in the partial answer below.)
For a template, ADL includes the namespaces and entities associated with the
types of the template arguments provided for template type parameters. Because the call to debugf includes this as a parameter, ADL will include namespace Bob because the template is instantiated with Bob::DeviceFrequency.
Updated example:
// Last change: 2020/10/30 11:15 EDT
#define MAKE_IT_WORK true // Modified (Example compiles)
namespace Bob { // Bob's project namespace
extern double thing; // (Added for answer testing)
struct Bar { int foo; }; // (Added for answer testing)
struct Foo { int bar; }; // (Added for answer testing)
extern Foo bar; // (Added for answer testing)
struct DeviceFrequency { double f; }; // (Modified: added "double f;")
extern void debugf(const char* fmt, ...);
static inline void function(DeviceFrequency& E) // (??TRICKY inference??)
{ debugf("default function, E: %f\n", E); }
} // namespace Bob
namespace SSN { // Super-Secret Namespace
namespace debugging {
extern int ssn_debug;
extern void debugf(const char* fmt, ...);
} // namespace debugging
} // namespace SSN
namespace SSN::signals { // Super-Secret Namespace, project signals
template<typename Coder>
class Frequency {
// Note: The Function type references the template indirectly, and has
// no purpose other than to make sure that a <Coder> function handler
// receives a <Coder&> parameter. ADL doesn't care. It brings in the
// Coder's namespace looking for functions to override.
typedef std::function<void(Coder&)> Function; // (Added) Another "gotcha"
const Function function; // This indirectly references Coder&, thus Bob
double thing= 543.21; // (Added) Duplicates name in namespace Bob
double f= 123.45; // (Added) Duplicates name in Bob::DeviceFrequency
Bob::Foo bar{876}; // (Added) Uses Bob namespace
struct Bar { int foo= 0x0F00; } foo; // (Added) Duplicates a Bob struct name
struct Derived : public Bob::Foo {}; // (Added) Uses Bob namespace
Derived secret{{671}}; // (Added) Uses Bob namespace in derived object
struct Container { int n= 888; Bob::Bar m{999}; }; // (Added) Uses Bob namespace
Container content; // (Added) Uses Bob namespace in container object
public:
// This constructor added to demonstrate indirect template references
Frequency( const Function& _function ) : function(_function)
{ using namespace ::SSN::debugging; // Without this, Bob::debugf is used
::SSN::debugging:: // Disambiguate
debugf("Frequency::Frequency(Coder: %p,%zd)\n", &_function, sizeof(_function));
// Drive the function, mostly just to see that it's been coded correctly
// Note the existence of function(DeviceFrequency& E) in namespace Bob.
// This *looks* like it might call Bob::function, but it doesn't,
// likely because function is an object containing an operator(), a
// std::function container.
Coder coder{2468}; function(coder); // (??TRICKY?? Not ADL ambiguous)
Coder rodoc{8642}; _function(rodoc); // (??TRICKY?? Not ADL ambiguous)
Bob::function(coder); // Just to verify it's different
}
Frequency( void ) // Default constructor
{ using namespace ::SSN::debugging; // Why isn't this enough??
using ::SSN::debugging::debugf; // Or this??
// Answer: When ADL comes into play, using statements are ignored.
// Also, without the first using, Bob::debugf would be used.
// (Rationale unclear, but that's the way it is.)
if( ssn_debug )
#if MAKE_IT_WORK
// As explained by #1201ProgramAlarm, it's the 'this' parameter that
// brought Bob's namespace into play for ADL name resolution.
// (Rationale unclear, but that's the way it is.)
::SSN::debugging:: // How can a developer predict that this is needed??
#endif
debugf("Frequency(%p,%zd)::Frequency\n", this, sizeof(*this));
// All remaining lines in Frequency added for detailed testing ============
const void* const that= this; // Another work-around
debugf("Frequency(%p,%zd)::Frequency\n", that, sizeof(*this)); // (Works)
Coder coder{3.14}; // (This is a Bob::DeviceFrequency)
debugf("Coder.f: %f\n", coder.f); // (No ambiguity)
Bob::debugf("Coder: %f\n", coder); // *** AMBIGUOUS debugf ***
debugf("f: %f\n", f); // (No ambiguity)
debugf("thing: %f\n", thing); // (No ambiguity)
debugf("Bob::thing: %f\n", Bob::thing); // (No ambiguity)
debugf("bar.bar: %d\n", bar.bar); // (No ambiguity)
SSN::debugging::debugf("bar: %d\n", bar); // *** AMBIGUOUS debugf ***
Bob::debugf("this->bar: %d\n", this->bar); // *** AMBIGUOUS debugf ***
debugf("foo.foo: 0x%3x\n", foo.foo); // (No ambiguity)
debugf("this->foo: 0x%3x\n", this->foo); // (No ambiguity)
debugf("Bob::bar.bar: %d\n", Bob::bar.bar); // (No ambiguity)
Bob::debugf("Bob::bar: %d\n", Bob::bar); // *** AMBIGUOUS debugf ***
debugf("secret.bar: %d\n", secret.bar); // (No ambiguity)
Bob::debugf("secret: %d\n", secret); // *** AMBIGUOUS debugf ***
debugf("content: %d\n", content); // (No ambiguity)
Bob::debugf("content.m: %d\n", content.m); // *** AMBIGUOUS debugf ***
// End of added lines =====================================================
}
}; // class Frequency
template<typename Coder>
struct Ugly_fix { // Macros stop ADL lookup, remove usings
#define debugf ::SSN::debugging::debugf
#define ssn_debug ::SSN::debugging::ssn_debug
Ugly_fix( void ) // Default constructor
{ if( ssn_debug ) debugf("Ugly_fix(%p)::Ugly_fix\n", this);
debugf("Bob::bar: %d\n", Bob::bar);
// Bob::debugf("Bob::bar: %d\n", Bob::bar); // Syntax error
}
#undef debugf // Macros (MUST BE) private
#undef ssn_debug
}; // struct Ugly_fix
class Non_template { public:
Non_template( void )
{ using namespace ::SSN::debugging;
if( ssn_debug )
debugf("Non_template(%p,%zd)::Non_template\n", this, sizeof(*this));
}
}; // class Non_template
} // namespace SSN::signals
// Namespace: **NONE**
static struct Handler { // Note: This actually *USES* ADL to find debugf
void operator()(Bob::DeviceFrequency& E) { debugf("E: %f\n", E); }
} handler; // struct Handler
struct Controller {
SSN::signals::Frequency<Bob::DeviceFrequency> bobcon;
SSN::signals::Frequency<Bob::DeviceFrequency> robcon;
SSN::signals::Ugly_fix<Bob::DeviceFrequency> ugly;
SSN::signals::Non_template non_template;
// Note that both Frequency constructors are used.
Controller( void ) : bobcon(), robcon(handler), ugly(), non_template() {}
}; // class Controller
// IMPLEMENTATION ============================================================
namespace SSN {
int debugging::ssn_debug= true;
namespace debugging {
void debugf(const char* fmt, ...) {
printf("SSN: "); // (For output disambiguation)
va_list argptr; va_start(argptr, fmt); vprintf(fmt, argptr); va_end(argptr);
} // debugf
} // namespace debugging
} // namespace SSN
namespace Bob {
double thing= 1122.33; // (Added for answer testing)
Foo bar{732}; // (Added for answer testing)
void debugf(const char* fmt, ...) {
printf("Bob: "); // (For output disambiguation)
va_list argptr; va_start(argptr, fmt); vprintf(fmt, argptr); va_end(argptr);
} // debugf
} // namespace Bob
// TEST ======================================================================
static inline int // Number of errors encountered
test_namespace_glitch( void ) // Test namespace glitch
{
int errorCount= 0; // Number of errors encountered
printf("\ntest_namespace_glitch\n");
Controller controller; // (Actually drive the constructor)
if( true ) {
errorCount++; // *Why* does 'this' import namespace?
printf("Still (partially) unexplained\n");
}
return errorCount;
}
(For those who like to run code, most of the test wrappers are also included here. You only need a main program that invokes the test.)
Here are the things I know I need to look out for:
Usage of this as a (bare) parameter inside of template code. (Thanks to #1201ProgramAlarm for pointing this "feature" out.) It's easy to do this accidentally, but hard to figure out why it happened.
Reference of an (uncontrolled) namespace named object (i.e. a struct or a class) used as a parameter to a function whether or not it's inside of template code. This is harder to do accidentally.
This reference can be indirect, as in the Frequency(const Function&) constructor, and therefore more prone to accidental use.
This may or may not be a complete list of ADL "gotcha's." There's a lot of examples in https://en.cppreference.com/w/cpp/language/adl that make me dizzy reading them, but the working ones don't usually seem to be things you might do accidentally once you've been bitten by ADL.
In my opinion, ADL shouldn't occur without explicit intent. Some language keyword or signal like [[adl]]std::swap(obj1,obj2) should be needed to activate it. But that's just me, I guess.
I don't know or understand the rationales behind the ADL design decisions to ignore using statements and to consider a bare this parameter a reference to a template object. I'm sure (OK, hoping) they exist. You may be interested in Andrew Koenig's short commentary A Personal Note About Argument-Dependent Lookup, found while diving into the mysteries of ADL in cppreference.com above.
Also, for the record, I'm up-voting and accepting #1201ProgramAlarm's answer because he explained that the this parameter brought ADL into play. When looking explicitly for it, I didn't find any documentation saying this would happen. While it doesn't answer my question, "How do I prevent this from happening?" I couldn't have gotten started without it.
What does help is that you get a seemingly unexplainable "ambiguous reference" error message that let's you know something strange and bad happened. Too late and too bad for whoever has to fix the problem. Too bad for someone who doesn't think about ADL, and might have to spend an inordinate amount of time first trying to isolate the problem and even then finally have to call on stackoverflow for help because ADL's just so weird.
I have an ugly way to bypass ADL, shown in the Ugly_fix constructor. By using (ugh) macros to auto-magically fully qualify names, not only is ADL prevented but the using statements are no longer needed. This kind of macro must be temporary, undefined after use, to avoid macro namespace pollution.
This question already has answers here:
Start thread with member function
(5 answers)
Closed 3 years ago.
When I compile the code below I get the following error. help me...!
Errors:
Error C2276 '&': illegal operation on bound member function expression
Error C3867 'CCore::Run': non - standard syntax; use '&' to create a pointer to member
I'm not sure if the program gives me an error.
I want to run the "Run" function of the Core class.
Core.cpp file contains only the functions created by the compiler.
I'm learning English so I'm not good yet. So please understand that the whole code.
// main.cpp
#include "Core.h"
#include <thread>
int main()
{
// The conditions below have been success
if (CCore::GetInstance().Init())
{
// The code below fails to compile.
// Error C3867 'CCore::Run': non - standard syntax; use '&' to create a pointer to member
thread main_thread(CCore::GetInstance().Run);
// Error C2276 '&': illegal operation on bound member function expression
thread main_thread(&CCore::GetInstance().Run);
main_thread.join();
}
return 0;
}
// Core.h
#pragma once
#include "Singleton.h"
#include <iostream>
using namespace std;
class CCore : public Singleton<CCore>
{
public:
CCore();
~CCore();
bool Init();
void Run();
};
// Singleton.h
#pragma once
template<typename T>
class Singleton
{
protected:
Singleton()=default;
~Singleton()=default;
public:
static T& GetInstance()
{
static T instance;
return instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton) = delete;
};
The compiler tells you the problem: Run() isn't a free function. It's a method, i.e. a function bound to an instance of an object. You have several options, but generally you either let the compiler synthesize a runnable for you, or write a free function yourself:
Let the compiler do all the work: guess what, it can make singletons for you so how cool is that?!
std::thread main_thread([]{
static CCore myCore;
myCore.Run();
});
You want to access that core? Sure!
std::future<CCore*> coreWhenDone = std::async([]{
static CCore myCore;
myCore.Run();
return &myCore;
});
Better yet, the core would provide some result, so that instead of accessing it directly when it's done, you could get its result (e.g. an int or std::vector<double> or whatever that core is computing)/
Let the compiler do some of the work:
std::thread main_thread([]{ CCore::GetInstance().Run(); });
Split the work between yourself and the compiler:
std::thread main_thread(std::bind(&CCore::Run, &CCore::GetInstance()));
Do all the work yourself:
void runCoreRun() {
CCore::GetInstance().Run();
}
...
std::thread main_thread(&runCoreRun);
I just started learning C++ for an Arduino project me and a friend have been working on. I'm getting the error "No matching function for call to 'QuadBase::QuadBase'" in main.cpp. I'not sure what is causing it, since I have the correct amount of arguments and they are the same type as well
edit: I brought it down to this and it still gives me that same error
#include <Arduino.h>
#include "QuadBase.h"
QuadBase base;
void setup()
{
base = QuadBase(
...
);
}
QuadBase.h
class QuadBase
{ public:
QuadBase( ... )
{
...
}
};
It seems your class QuadBase is missing a default constructor (one that takes no arguments) which is needed for the line
QuadBase base;
I just started writing some code for a class what will be an engine for an analysis, it's simple right now since I'm getting to grips with the stuff I can do with the libraries I import (the bpp ones):
#include <string>
#include <iostream> //to be able to output stuff in the terminal.
#include <Bpp/Seq/Alphabet.all> /* this includes all alphabets in one shot */
#include <Bpp/Seq/Container.all> /* this includes all containers */
#include <Bpp/Seq/Io.all> /* this includes all sequence readers and writers */
class myEngine
{
public:
myEngine();
~myEngine();
void LoadSeq();
};
void myEngine::LoadSeq()
{
bpp::Fasta fasReader;
bpp::AlignedSequenceContainer *sequences = fasReader.readAlignment("tester.fasta", &bpp::AlphabetTools::DNA_ALPHABET);
std::cout << "This container has " << sequences->getNumberOfSequences() << " sequences." << std::endl;
std::cout << "Is that an alignment? " << (bpp::SequenceContainerTools::sequencesHaveTheSameLength(*sequences) ? "yes" : "no") << std::endl;
}
int main()
{
myEngine hi();
hi.LoadSeq();
return 0;
}
I've not defined a constructor or destructor since they take no arguments right now and there aren't any member variable except a member function which returns nothing, just loads a file and prints to cout.
However trying to compile does not work:
rq12edu#env-12bw:~/Desktop/TestingBio++$ make
g++ main.cpp -o mainexec --static -I/local/yrq12edu/local/bpp/dev/include -L/local/yrq12edu/local/bpp/dev/lib -lbpp-seq -lbpp-core
main.cpp: In function 'int main()':
main.cpp:26:5: error: request for member 'LoadSeq' in 'hi', which is of non-class type 'myEngine()'
make: *** [all] Error 1
Maybe I'm being thick but I don't see why it's not letting me execute LoadSeq when I've defined it as a public member of myEngine, why is it erroring when it requests it from the hi instance of myEngine?
Thanks,
Ben W.
This:
myEngine hi();
declares a function, not an object. To declare and default-construct an object, remove the parentheses:
myEngine hi;
In this line:
myEngine hi();
You declare a function hi that returns instance of type myEngine.
Change it either to:
myEngine hi()
or
myEngine hi = myEngine();
This statement
myEngine hi();
is a function declaration with name hi having return type myEngine and no parameters.
Write instead
myEngine hi;
Or
myEngine hi {};
Take into account that you did not define the default constructor and the destructor (at least you did not show their definitions). That the code would ve compiled you couls define it the following way
class myEngine
{
public:
myEngine() = default;
~myEngine() = default;
//...
Or you could remove these declarations (and definitions) and use implicitly defined by the compiler constructor and destructor.
Currently I am trying to get the following code to compile:
terminallog.hh
#ifndef TERMINALLOG_HH
#define TERMINALLOG_HH
#include <string>
#include <sstream>
#include <iostream>
class Terminallog {
public:
Terminallog();
virtual ~Terminallog();
class Warn {
public:
Warn();
private:
bool lineended;
};
friend class Terminallog::Warn;
protected:
private:
Warn warn;
};
terminallog.cc
// stripped code
Terminallog::Terminallog() {
Warn this->warn();
}
Terminallog::Warn::Warn() {
this->lineended = true;
}
//stripped code
Well, as you probably guessed alredy, its failing ;-). My compiler is saying:
g++ src/terminallog.cc inc/terminallog.hh -o test -Wall -Werror
In file included from src/terminallog.cc:8:
src/../inc/terminallog.hh:56: error: declaration of ‘Terminallog::Warn Terminallog::warn’
src/../inc/terminallog.hh:24: error: conflicts with previous declaration ‘void Terminallog::warn(std::string)’
which leaves me out of options. I am obviously doing something wrong, however I have no idea of how to resolve this. I would appreciate any hints.
Thanks in advance
ftiaronsem
Warn this->warn(); is not valid C++ syntax - if you want to initialize the warn member, use an initialization list (you don't need to in this case - the default constructor is called implicitly!).
Terminallog::Terminallog() : warn()
{
// other constructor code
}
// note that `Warn::Warn()` is invoked implicitly on `wake`, so
TerminalLog::Terminallog() {}
// would be equivalent