How can I access private member variable with a friend function that has a requires
expression? Is there a way to get the code to compile without removing requires std::is_default_constructible_v<T>
?
#include <iostream>
#include <type_traits>
template<typename T>
class Y
{
static constexpr int data = 10;
template <typename U>
friend U pp();
};
template<typename T>
requires std::is_default_constructible_v<T>
T pp()
{
std::cout << Y<T>::data << '\n';
return T();
}
int main() {
pp<int>();
return 0;
}
Gives error
error: 'constexpr const int Y<int>::data' is private within this context
How can I access private member variable with a friend function that has a requires
expression? Is there a way to get the code to compile without removing requires std::is_default_constructible_v<T>
?
#include <iostream>
#include <type_traits>
template<typename T>
class Y
{
static constexpr int data = 10;
template <typename U>
friend U pp();
};
template<typename T>
requires std::is_default_constructible_v<T>
T pp()
{
std::cout << Y<T>::data << '\n';
return T();
}
int main() {
pp<int>();
return 0;
}
Gives error
error: 'constexpr const int Y<int>::data' is private within this context
1 Answer
Reset to default 5Note you can have mutiple versions of pp()
template with different requriements.
For example this is valid code:
template<typename T>
T pp()
{
std::cout << "I do not need friendships\n";
return T();
}
template<typename T>
requires std::is_default_constructible_v<T>
T pp()
{
std::cout << Y<T>::data << '\n';
return T();
}
When overload resolution is performed and there are multiple choices with concepts, most specialized version is selected.
So in your code you have declared two versions of pp()
like in my example above. One is declared when friendship is defined and other outside a Y
class.
As a result Y
is friended with a function template which has missing implementation.
So to fix this you must use same concept to funtion tempalte as in function template definition:
template<typename T>
class Y
{
static constexpr int data = 10;
template <typename U>
requires std::is_default_constructible_v<U>
friend U pp();
};
template<typename T>
requires std::is_default_constructible_v<T>
T pp()
{
std::cout << Y<T>::data << '\n';
return T();
}
After that it works as expected: https://godbolt./z/jGEqzhdsW
Moving definition of template inside a class fixes this issue by coincidence, sine at same time you are moving a concept there.
pp
function from the entirely differenttemplate<typename T> requires (!std::is_default_constructible_v<T>) T pp()
? – MSalters Commented Feb 10 at 15:34