c++20 concept limited by member access specifier [duplicate] - c++

Is it possible to make this code work as I'd like? I.e. to allow the concept to have access to a private member funcion?
template <typename T>
concept bool Writeable()
{ return requires (T x,std::ostream os) { { x.Write(os) } -> void }; }
template <Writeable T>
void Write(std::ostream &os,const T &x) { x.Write(os); }
class TT
{
private:
void Write(std::ostream &os) const { os << "foo"; }
//friend concept bool Writeable<TT>();
friend void ::Write<TT>(std::ostream &,const TT &);
};
Thanks

No. Concepts explicitly are not allowed to be friends.
n4377 7.1.7/2
Every concept definition is implicitly defined to be a constexpr
declaration (7.1.5). A concept definition shall not be declared with
the thread_local, inline, friend, or constexpr specifiers, nor shall a
concept definition have associated constraints (14.10.2).
We can reduce it to this example to show that the access really is the problem:
template <typename T>
concept bool Fooable = requires (T t) { { t.f() } -> void };
struct Foo
{
private:
void f() {}
};
int main()
{
static_assert(Fooable<Foo>, "Fails if private");
}
You can however use a level of indirection, something like this:
template <typename T>
void bar(T t) { t.f(); }
template <typename T>
concept bool FooableFriend = requires(T t) { { bar(t) } -> void };
struct Foo
{
private:
void f() {}
template<typename T>
friend void bar(T t);
};
int main()
{
static_assert(FooableFriend<Foo>, "");
}
Live demo incorporating your example
Which works. Concepts are pretty early, so I imagine down the line that they might lift the friend restriction just as proposals have lifted restrictions for C++11/14 features in the past.

Related

Templated multistack implementation - how?

I need a 'MultiStack' taking different types of objects, putting each type in a separate stack.
This is what it looks like so far. The open problem is: how to handle the containers for a number of different T
class MultiStack
{
public:
template<typename T>
const T& Get()
{
return Container<T>.back();
}
template<typename T>
void Push( const T& t )
{
Container<T>.push_back( t );
}
template<typename T>
void Pop( const T& /*t*/ )
{
Container<T>.pop_back();
}
private:
// this does not make sense, we obv. need one stack for each T
// template<typename T>
// std::vector<T> Container;
};
Now, I could use the old trick, putting the Container in a member function, like
template<typename T>
auto GetContainer()
{
static std::vector<T> C;
return C;
}
but I don't like this anymore in the age of multi-threading. It is 'dangerous', right!?
Is there a better, elegant way? It is conceivable that I know the allowed types beforehand, if that helps realizing it.
but I don't like this anymore in the age of multi-threading. It is 'dangerous', right!?
Issue is not multi-threading. initialization would be fine.
You still have to protect/synchronize access though, as regular multi-threading code.
Issue is that the container is not per instance of MultiTask, as it is static.
It is mostly as if MultiTask were a Singleton.
It is conceivable that I know the allowed types beforehand, if that helps realizing it.
That helps, you can then use std::tuple, something like (C++14):
template <typename ... Ts>
class MultiStack
{
public:
template<typename T>
const T& Get() const
{
return GetContainer<T>().back();
}
template<typename T>
void Push(const T& t)
{
GetContainer<T>().push_back(t);
}
template <typename T>
void Pop()
{
GetContainer<T>().pop_back();
}
private:
template <typename T>
const std::vector<T>& GetContainer() const { return std::get<std::vector<T>>(Containers); }
template <typename T>
std::vector<T>& GetContainer() { return std::get<std::vector<T>>(Containers); }
private:
std::tuple<std::vector<Ts>...> Containers;
};

Is it possible to declare a template function with 'auto' return type as a friend of a class?

How to declare the following function as a friend of a class
template <class T>
inline auto func(T & val)
{
//return ...;
}
class A { friend auto func<A>(A & val); }
Is it legal?
Yes, you can get it to work from C++14 on.
How to do it?
You can do it like this (see here):
class A;
template <class T>
inline auto func(T& val);
class A
{
friend auto func<A>(A& val);
int j = 6;
};
template <class T>
inline auto func(T& val)
{
return val.j;
}
int main()
{
A a;
return func<A>(a);
}
However, I agree with the comments: the question could be improved if you provided an exact problem for which we could try finding an answer.

C++ concept with friend-like access

Is it possible to make this code work as I'd like? I.e. to allow the concept to have access to a private member funcion?
template <typename T>
concept bool Writeable()
{ return requires (T x,std::ostream os) { { x.Write(os) } -> void }; }
template <Writeable T>
void Write(std::ostream &os,const T &x) { x.Write(os); }
class TT
{
private:
void Write(std::ostream &os) const { os << "foo"; }
//friend concept bool Writeable<TT>();
friend void ::Write<TT>(std::ostream &,const TT &);
};
Thanks
No. Concepts explicitly are not allowed to be friends.
n4377 7.1.7/2
Every concept definition is implicitly defined to be a constexpr
declaration (7.1.5). A concept definition shall not be declared with
the thread_local, inline, friend, or constexpr specifiers, nor shall a
concept definition have associated constraints (14.10.2).
We can reduce it to this example to show that the access really is the problem:
template <typename T>
concept bool Fooable = requires (T t) { { t.f() } -> void };
struct Foo
{
private:
void f() {}
};
int main()
{
static_assert(Fooable<Foo>, "Fails if private");
}
You can however use a level of indirection, something like this:
template <typename T>
void bar(T t) { t.f(); }
template <typename T>
concept bool FooableFriend = requires(T t) { { bar(t) } -> void };
struct Foo
{
private:
void f() {}
template<typename T>
friend void bar(T t);
};
int main()
{
static_assert(FooableFriend<Foo>, "");
}
Live demo incorporating your example
Which works. Concepts are pretty early, so I imagine down the line that they might lift the friend restriction just as proposals have lifted restrictions for C++11/14 features in the past.

C++ Template - In-class Struct

For the following code, I got a compilation error at implementation line as:
"B does not define a type".
I am aware of solution of put the function definition inside of class declaration. Is it possible, though, to have the function definition out of the template class declaration? Thanks
template<typename T>
class A {
public:
// ctor, dtor and interface funcs etc
private:
struct B {
T value;
B *next;
}
B *locate(const T& val) const;
// blah blah
};
template<typename T>
B *A<T>::locate(const T& val) const
{
//logic
}
Since B is defined inside A you should qualify it with A<T>:::
template<typename T>
typename A<T>::B *A<T>::locate(const T& val) const
{
//logic
}
Also note typename which is required because B is a dependent name.

Accessing private member variables inside public member function

In function myfun is there a way to access rhs.var without writing a public function which returns var? Also, as I understand, this happens because rhs could be a different type... Is this correct?
#include <iostream>
template<class T>
class foo
{
private:
T var;
public:
foo(T v) : var(v) {}
template<class Type>
void myfun(foo<Type>& rhs)
{
auto i = rhs.var; //BOOM
}
};
int main()
{
foo<int> a = 5;
foo<double> b = 2.2;
a.myfun(b);
}
Suggested Solutions
You could either provide a public accessor to your private member variable:
template<class T>
class foo {
T var;
public:
foo(T v) : var(v) {}
T getVar() const { return var; }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
template<class Type>
void myfun(foo<Type>& rhs) {
auto i = rhs.getVar();
^^^^^^^^
}
};
Or as already Dieter mentioned in the comments you could make your template class a friend:
template<class T>
class foo {
T var;
template <class> friend class foo;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
public:
foo(T v) : var(v) {}
template<class Type>
void myfun(foo<Type>& rhs) {
auto i = rhs.var;
}
};
Overview
The reason why the template member function myfun is not granted access to private member variable var of class template foo is that the compiler interprets class foo<Type> and class foo<T> as completely different class types, even though they would originate from the same template class definition. Thus, as being different class types the one cannot access the private members of the other.
you can define the second type as fried like:
template<class T>
class foo
{
private:
T var;
public:
foo(T v) : var(v) {}
template<class Type>
void myfun(foo<Type>& rhs)
{
auto i = rhs.var; //BOOM
}
template<class Type>
friend class foo;
};
live example