Circular dependency in C++ template methods - c++

I've got a problem with a circular dependecy in C++ template methods. I realize there are several similar threads here but they didn't help me with my specific case. This here is a nonsensical example, but it illustrates the issue:
main.cpp
#include "A.h"
int main()
{
float f = 10;
A a;
a.foo( f );
}
A.h
#pragma once
#include "B.h"
#include <iostream>
class A
{
private:
B _b;
public:
A() {}
std::string getName() const { return "A"; }
template<typename T> void foo( T t )
{
if( _b.getActive() )
_b.foo( t, this );
else
std::cout << "A, " << t << std::endl;
}
};
B.h
#pragma once
#include "A.h"
#include <string>
#include <iostream>
class A;
class B
{
private:
bool _active;
public:
B() : _active( false ) {}
bool getActive() const { return _active; }
void setActive( bool active ) { _active = active; }
template<typename T> void foo( T t, const A *a )
{
std::cout << "B, " << a->getName() << std::endl;
}
};
In B.h I can neither forward-declare A (will get error C2039: 'getName': is not a member of 'A'), nor include A.h (will get error C4430: missing type specifier - int assumed.).
Is there a way around this or do I have to completely refactor my code?
EDIT
I'm compiling with MSVC 141 (VS 2017) with /std:c++latest, btw.

The problem here is that getName() in a->getName() is a non-dependent name (it does not depend on the template parameter T), and it is resolved at the point of template definition. But A is incomplete at that point.
As a simple but ugly workaround, we can introduce a fake dependency on T:
template<class T, class S>
struct First {
using Type = T;
};
struct A;
struct B {
template<typename T>
void foo(T t, const typename First<A, T>::Type* a) {
std::cout << "B, " << a->getName() << std::endl;
}
};
A cleaner solution is to move foo() definitions outside classes and include them after both A and B:
// A.h
#pragma once
#include "B.h"
class A {
// ...
template<typename T>
void foo(T t);
};
// A_impl.h
#pragma once
#include "A.h"
template<typename T>
void A::foo(T t) {
// ...
}
// Similar for B.h and B_impl.h
// main.cpp
#include "A_impl.h"
#include "B_impl.h"
int main() {
float f = 10;
A a;
a.foo(f);
}

I'd also like to add a (not so nice) solution, but maybe it's helpful for some:
during investigations it struck me that I had a different project using the same code base which does compile without any issues. I noticed the difference was the new project had the Conformance Mode set to /permissive-, while the old one had not. So if you need a quick solution for MSVC and don't care about standard conformance, you may want to turn this option off. This way, the above code works just as posted.
EDIT
Disclaimer: be aware though that this may break code, as Evg points out in the comment below.

Related

Use of incomplete types with std::variant

Suppose I have next code, that is used for simply storing reference/pointer to objects of types A, B or C. I actually don't need complete types.
Now i have the following solution, where I need a lot of #include bloat.
Header:
using MyVariant = std::variant<class A, class B, class C, ...>;
class Holder {
public:
Holder(MyVariant &&TheValue);
const MyVariant &GetValue();
private:
std::unique_ptr<MyVariant> Value;
};
Source file:
#include "A.hpp"
#include "B.hpp"
#include "C.hpp"
Holder::Holder(MyVariant &&TheValue)
: Value(std::make_unique<MyVariant>(std::move(TheValue)) {}
const MyVariant &Holder::GetValue { return Value; }
How I can implement the same semantics without all instantiated types as std::variant template parameters / dynamic memory allocation / dynamic polymorphism?
As others have pointed out the specifications seem a little contradicting.
I can only think of variable template arguments, to achieve not having to specify all possible classes for the Holder class.
Example
#include <iostream>
#include <memory>
#include <variant>
// h
template<typename ...T>
class Holder {
using variant = std::variant<T...>;
public:
Holder(variant &&TheValue)
:Value(std::make_unique<variant>(std::move(TheValue)))
{
};
template<typename TARGET>
const TARGET &GetValue() const {
return std::get<TARGET>(*Value);
};
private:
std::unique_ptr<variant> Value;
};
// main.cpp testing
int main() {
auto a = Holder<int, float>(5);
const auto v = a.GetValue<int>();
std::cout << "holding int: " << v << std::endl;
a = Holder<int, float>(5.5f);
const auto v2 = a.GetValue<float>();
std::cout << "holding float: " << v2 << std::endl;
}
I think at that point it looks like a rather redundant class though.

Make int overload a preferable one

Consider following code snippet:
class Foo {
public:
void bar(std::size_t){}
void bar(const char* ){}
};
int main() {
auto foo = Foo{};
foo.bar(0);
}
It produces ambiguous calls errors (check here). But I think from programmer's perspective it is pretty obvious that I want to call overload with std::size_t. My question is if anything can be done so this code does not produce errors and calls size_t overload?
can be done like this in C++ 20
#include <cstdint>
#include <iostream>
#include <type_traits>
class Foo {
public:
template <typename T>
requires std::is_integral_v<T>
void bar(T){
std::cout<<"hello size_T";
}
void bar(const char* ){
std::cout<<"hello";
}
};
int main() {
auto foo = Foo{};
foo.bar(25);
}
In modern c++ (at least c++17), we prefer to pass string_view as argument over const char* for the none owner transfer cases, so a considerable choice:
#include <cctype>
#include <string>
class Foo {
public:
void bar(std::size_t){}
void bar(std::string_view){}
};
int main() {
auto foo = Foo{};
foo.bar(0);
}
Online demo
In below C++ 20, this works well.
#include <iostream>
class Foo {
public:
template <typename T>
void bar(T) {
std::cout << "hello T" << std::endl;
}
void bar(const char* c) {
std::cout << c << std::endl;
}
};
int main() {
auto foo = Foo{};
foo.bar(0);
foo.bar("test.");
}
This works in C++23:
foo.bar(0zu);
and this works pre-C++23:
foo.bar(size_t{0});

C++ syntactic sugar or technique for prototype generation when using template specialization

I wonder what is the preferred C++ way for the generation of method prototypes,
when using template specialization? The technique I'm after
should scale well with the number of the foo class methods, see below.
The marked block of the reproducer has to be replaced.
Please no code snippets managed by hand or by a script.
Some additional small modifications (perhaps in the header) might be possible.
For brevity the templated class A is placed beside the typedef for Aint.
CRTP solutions are disfavored. Usage of C++17 (not later) is allowed.
Has to compile with VS2019 recent g++ and clang++.
Edit 2020-02-09:
Removing the marked block all together,
this compiles fine with
Compiler Explorer's x64 MSVC 19.14 compiler.
So do we have a compiler issue here for g++ and clang++?
// begin of testspec.h
template<class T>
class A
{
public:
A();
void foo1();
void foo2();
void foo3();
};
typedef A<int> Aint;
// end of testspec.h
// begin of testspec.cpp
#include "testspec.h"
#include <iostream>
/////////////// can this block be simplified? //////////
template<>
void
A<int>::foo1();
template<>
void
A<int>::foo2();
template<>
void
A<int>::foo3();
/////////////// can this block be simplified? //////////
template<>
A<int>::A()
{
foo1();
foo2();
foo3();
std::cout << "hello world" << std::endl;
}
template<>
void
A<int>::foo1()
{
std::cout << "foo1" << std::endl;
}
template<>
void
A<int>::foo2()
{
std::cout << "foo2" << std::endl;
}
template<>
void
A<int>::foo3()
{
std::cout << "foo3" << std::endl;
}
// end of testspec.cpp
// begin of main.cpp
#include "testspec.h"
int main()
{
Aint a;
return 0;
};
// end of main.cpp
Assuming that there is a part of A that does not get specialized, then the portion of A that you are trying to allow for modifiable behavior via specialization can be accomplished by adopting a policy pattern.
class APolicy {
template <class, class> friend class A;
void foo1 ();
void foo2 ();
void foo3 ();
};
template <class T, class P = APolicy>
class A {
void foo1() { P().foo1(); }
void foo2() { P().foo1(); }
void foo3() { P().foo1(); }
};
And then instead of specializing A<int>, you implement a policy IntPolicy, and then instantiate A<int, IntPolicy>.

How to have a c++ object with a method that takes argument the enclosing class?

I am trying to figure out if there's any known pattern/idiom in c++ for what I am trying to do here. Class A must be composed of an object that has a function whose argument must also be of type A. The following code doesn't compile since typeid may not be used in a constant expression. Any suggestions?
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
struct B {
int f(T& i) { cout << "Hello\n"; }
};
class A {
B<typeid(A)> b;
};
int main()
{
A k;
}
Your stated requirements don't need templates at all, just a forward declaration:
#include <iostream>
class A; // forward declare A
struct B {
int f(A &i); // declaration only, definition needs the complete type of A
};
class A {
B b;
};
int B::f(A &i) { std::cout << "Hello\n"; } // define f()
int main()
{
A k;
}
You are looking for B<A> b; The following program compiles without error or warning on g++ 4.4.3.
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
struct B {
int f(T& i) { cout << "Hello\n"; return 0; }
};
class A {
public:
B<A> b;
};
int main()
{
A k;
return k.b.f(k);
}
Note: If you are using templates only to avoid forward declaration, my solution is wrong. But, I'll leave it here in case you are using templates for some other legitimate reason.

How to create a library that wraps an object with a template function using minimal includes?

The goal of this project is to create a library for distribution. In the past, I used forward declares so I didn't have to distribute a bunch of header files along with the libraries. However, I'm now trying to eliminate code duplication by switching to templates and am running into some issues.
First, a simple example project showing what is currently working:
//LibraryDep1.h
class LibraryDep1
{
public:
LibraryDep1(void) {};
virtual ~LibraryDep1(void) {};
template <typename T>
int TestFunction(T value)
{
std::cout << value << std::endl;
return 0;
}
};
//LibraryInclude.h
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
int TestFunction(int value);
int TestFunction(std::string value);
};
//LibraryInclude.cpp
#include "LibraryInclude.h"
#include "LibraryDep1.h"
LibraryInclude::LibraryInclude(void)
{
this->mLibDep1 = new LibraryDep1();
}
LibraryInclude::~LibraryInclude(void)
{
delete this->mLibDep1;
}
int LibraryInclude::TestFunction(int value)
{
return this->mLibDep1->TestFunction(value);
}
int LibraryInclude::TestFunction(std::string value)
{
return this->mLibDep1->TestFunction(value);
}
//main.cpp
#include <tchar.h>
#include "LibraryInclude.h"
int _tmain(int argc, _TCHAR* argv[])
{
LibraryInclude inclLibrary;
inclLibrary.TestFunction(77);
inclLibrary.TestFunction("test");
}
This gives the expected output of:
77
test
However, the overloads of LibraryInclude::TestFunction could be replaced with a template function to further reduce code duplication:
//LibraryInclude.h
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
template <typename T>
int TestFunction(T value) {
return mLibDep1->TestFunction(value);
}
};
The problem now is that I'm using mLibDep1 without including the full implementation giving me an undefined type compilation error. Meaning that I need to #include "LibraryDep1.h" in LibraryInclude.h, thus requiring me to distribute both LibraryInclude.h and LibraryDep1.h with my library. This is a simple example, the real project has many header files that would need to be distributed if I were to switch to using the templated version of LibraryInclude.
My question is, is there any way to avoid having to distribute a bunch of include files with my library and eliminate code duplication? Or, am I better off just overloading for all known types (drastically reducing library flexibility) in the distributed header file and keeping the templates in only the underlying classes?
No. There is currently no way to do what you want. When compiler vendors start implementing the 'export' keyword you'll be in luck. Currently I only know of Comeau doing so. This keyword has been around for years so I wouldn't hold my breath until the rest implement it.
A very limited and ugly solution would be:
//LibraryDep1.h
#pragma once
#include <iostream>
class LibraryDep1
{
public:
LibraryDep1(void) {};
virtual ~LibraryDep1(void) {};
template <typename T>
int TestFunction(T value)
{
std::cout << value << std::endl;
return 0;
}
};
//LibraryInclude.h
#pragma once
class LibraryDep1; //forward declare
class LibraryInclude
{
private:
LibraryDep1* mLibDep1;
public:
LibraryInclude(void);
virtual ~LibraryInclude(void);
template <typename T>
int TestFunction(T value);
};
//LibraryInclude.cpp
#include "LibraryInclude.h"
#include "LibraryDep1.h"
#include <string>
LibraryInclude::LibraryInclude(void)
{
mLibDep1 = new LibraryDep1();
}
LibraryInclude::~LibraryInclude(void)
{
}
// only to save some typing when only forwaring calls
#define LI_TESTFUNCTION( TYPE ) \
template<> \
int LibraryInclude::TestFunction<TYPE>( TYPE value ) {\
return mLibDep1->TestFunction(value); \
}
// the allowed specializations, everything else causes link errors
LI_TESTFUNCTION( int );
LI_TESTFUNCTION( std::string );
Tested this with VC++ 2k8 & g++ 4.3.4 statically linking against LibraryInclude.o