Reputation: 371
I have the following scenario:
struct AP;
struct B
{
B() : m(2) {}
int m;
};
struct A : private B
{
A() : B(), n(1) {}
private:
int n;
friend AP;
};
struct AP
{
AP(A& a) : a_(a) {}
template<typename T>
struct A_B {
using type = typename std::enable_if< std::is_base_of< typename std::remove_reference<T>::type,
A >::value,
T >::type;
};
template<typename T>
operator typename A_B<T>::type()
{
return static_cast<T>(a_);
}
template<typename T>
typename A_B<T>::type get()
{
return static_cast<T>(a_);
}
int& n() { return a_.n; }
private:
A& a_;
};
int main()
{
A a;
AP ap(a);
ap.n() = 7;
const B& b = ap.get<const B&>();
//const B& b = ap; candidate template ignored: couldn't infer template argument 'T'
//auto b = static_cast<const B&>(ap); candidate template ignored: couldn't infer template argument 'T'
std::cout<<b.m;
}
The commented lines wouldn't compile. Clang++ notes that "candidate template ignored: couldn't infer template argument 'T'"
Why am I not able to get a reference to A's base with the cast operator? I think the code would look much nicer that way.
Upvotes: 3
Views: 1635
Reputation: 41092
The answer that you posted works, but is overkill unless you really want a static_assert
message.
Classic templating works just fine in this instance because A
is already convertible to B
:
struct AP
{
AP(A& a) : a_(a) {}
template<typename T>
operator T()
{
return a_;
}
template<typename T>
T get()
{
return a_;
}
int& n() { return a_.n; }
private:
A& a_;
};
Upvotes: 1
Reputation: 371
I found the answer here: http://www.mersenneforum.org/showthread.php?t=18076
This is the key: "when you want the compiler to deduce argument types, those types must not be dependent types"
With this it compiles:
template<typename T>
operator T()
{
static_assert(std::is_base_of< typename std::remove_reference<T>::type,A >::value,
"You may cast AP only to A's base classes.");
return static_cast<T>(a_);
}
Upvotes: 0