So I was trying to write a default function version when there are no template arguments passed in the following code:
struct A{ int x; };
struct B : public A { int y;};
struct C {
void set(const A& v) { v_ = v; }
template <typename T>
const T& get() { return reinterpret_cast<T&>(const_cast<A&>(v_)); }
template <>
const A& get() { return v_;}
A v_;
};
int main() {
B b;
C c;
c.set(b);
(void)c.get<B>().y;
(void)c.get<A>().x;
//(void)c.get().x; << Error
}
But it doesn't work at the indicated Error line above with this error:
test.cpp:22:13: error: no matching member function for call to 'get'
(void)c.get().x;
~~^~~
test.cpp:9:14: note: candidate template ignored: couldn't infer template argument 'T'
const T& get() { return reinterpret_cast<T&>(const_cast<A&>(v_)); }
^
1 error generated.
I do understand the issue that since no template argument was passed in the client call, it was unable to infer the typename but is there a way to provide a default implementation like the one in the above code when that happens? Essentially I want to avoid writing client code as (void)c.get<A>().x; and instead, adopt the default route implicitly.
As an alternative solution, you can specify A as default template argument for parameter T, e.g.
struct C {
void set(const A& v) { v_ = v; }
template <typename T = A>
const T& get() { return reinterpret_cast<T&>(const_cast<A&>(v_)); }
template <>
const A& get() { return v_;}
A v_;
};
int main() {
B b;
C c;
c.set(b);
(void)c.get<B>().y; // call the primary template
(void)c.get<A>().x; // call the specification
(void)c.get().x; // call the specification
}
You can delete the template <> part.
struct C {
void set(const A& v) { v_ = v; }
template <typename T>
const T& get() { return reinterpret_cast<T&>(const_cast<A&>(v_)); }
const A& get() { return v_;}
A v_;
};
Related
Is it possible to have the template specialization of a base type chosen for the derived types? If not, what is a possible solution to the following without having to specialize for each derived type?
NOTE: This is a simplified version of our validator. Different types have different validation requirements
template <typename T>
class IsValid_Executor
{
public:
auto IsValid(const T& InObj) -> bool = delete;
};
class Bar { };
class Foo : public Bar { };
template <>
class IsValid_Executor<void*>
{
public:
auto IsValid(const void* InObj)
{
return InObj != nullptr;
}
};
template <>
class IsValid_Executor<Bar*>
{
public:
auto IsValid(const Bar* InObj)
{
return InObj != nullptr;
}
};
template <typename T>
bool IsValid(const T& InObj)
{
return IsValid_Executor<T>{}.IsValid(InObj);
}
int main()
{
Bar* b;
IsValid(b); // compiles
Foo* f;
IsValid(f); // error: use of deleted function
IsValid_Executor<void*>{}.IsValid(f); // compiles
IsValid_Executor<decltype(f)>{}.IsValid(f); // error: use of deleted function - why isn't the void* OR the Bar* overload chosen?
IsValid_Executor<Bar*>{}.IsValid(f); // compiles - however, I cannot know in the `IsValid<T>` function to choose Bar*
}
You can use partial specialization for all the derived classes of Bar.
template <typename T, typename = void>
class IsValid_Executor
{
public:
auto IsValid(const T& InObj) -> bool = delete;
};
then
template <typename D>
class IsValid_Executor<D*, std::enable_if_t<std::is_base_of_v<Bar, D>>>
{
public:
auto IsValid(const Bar* InObj)
{
return InObj != nullptr;
}
};
LIVE
I want to explicitly instantiate template member but without instantiation of the template class. But I am getting compiler errors, so is this possible ? Here is my code:
//mytemplate.h
template <class T>
class mytemplate
{
public:
mytemplate(T* tt)
{
mT = tt;
}
template<class B>
void print(const B& bb);
T* mT;
};
//in mytemplate.cpp
#include "mytemplate.h"
template<typename T>
template<typename B>
void mytemplate<T>:: print(const B& bb)
{
B b = bb;
}
template<typename T> void mytemplate<T>::print<float>(const float&) const;
template<typename T> void mytemplate<T>::print<int>(const int&) const;
// main.cpp
int main()
{
int d =0;
mytemplate<int> k(&d);
k.print<float>(4.0);
}
With templates, it always helps to decompose the problem into the smallest possible building block. mytemplate::print can be written in terms of a call to a template free function.
This way you can achieve the effect of partial specialisation of a member function.
A leading question here is "what should the print() method do?". Here is an example in which mytemplate<T> provides a printing policy to a free function. There is no reason of course that the policy could not be some other class which has been constructed via some other (possibly specialised) template free function.
// Policy is a concept which supports 2 methods:
// print_prefix() and print_postfix()
//
template<class Policy, class B>
void print_with_policy(const Policy& policy, const B& value) const
{
policy.print_prefix();
cout << value;
policy.print_postifx();
}
template<class T>
struct mytemplate
{
// implement in terms of a free function
template<class B> void print(const B& value) {
print_with_policy(*this, value);
}
// policy concept implementation
void print_prefix() const {
cout << "prefix-";
}
void print_postfix() const {
cout << "-postfix";
}
};
extending the example to use a separate policy class with a specialisation for strings:
template<typename B>
struct default_policy {
default_policy(const B& value) : _value(value) {}
void operator()() const {
cout << "(" << _value << ")";
}
private:
const B& _value;
};
template<typename B>
struct quoted_policy {
quoted_policy(const B& value) : _value(value) {}
void operator()() const {
cout << '"' << _value << '"';
}
private:
const B& _value;
};
template<class B>
default_policy<B> make_policy(const B& value) {
return default_policy<B>(value);
}
// overload for B being a string
quoted_policy<std::string> make_policy(const std::string& value) {
return quoted_policy<std::string>(value);
}
template<class T>
struct mytemplate
{
// implement in terms of a free function
template<class B> void print(const B& value) {
make_policy(value)();
cout << endl;
}
};
int main()
{
struct foo{};
mytemplate<foo> fooplate;
fooplate.print(int(8));
fooplate.print(std::string { "a string" });
fooplate.print("not a string");
return 0;
}
output:
(8)
"a string"
(not a string)
I am trying to wrap some templated functions into some binary functors like below. When I try to compile the code I have the error
error: no match for call to ‘(QtyAsc) (myobj&, myobj&)
I thought that being operator() in QtyAsc a function in a class, the template deduction mechanism would have worked but it seems that the compiler doesn't accept myobj classes as valid types for it.
Is it maybe because of the call to boost::bind? I was trying to provide a default implementation for the second templated argument (unfortunately I cannot use C++11 with default templated arguments).
class myobj {
public:
myobj(int val) : qty_(val) {}
int qty() { return qty_;}
private:
int qty_;
};
template<class T>
int get_quantity(const T& o) {
throw runtime_error("get_quantity<T> not implemented");
}
template<>
int get_quantity(const myobj& o) {
return o.qty();
}
struct QtyAsc {
template<class T, class QEx >
bool operator()(const T& o1, const T& o2, QEx extr = boost::bind(&get_quantity<T>,_1)) const {
if(extr(o1) < extr(o2))
return true;
return false;
}
};
int main() {
myobj t1(10),t2(20);
QtyAsc asc;
if(asc(t1,t2))
cout << "Yes" << endl;
}
If you can't use C++11, just provide an additional overload:
struct QtyAsc {
template<class T, class QEx >
bool operator()(const T& o1, const T& o2, QEx extr) const {
return extr(o1) < extr(o2);
}
template<class T>
bool operator()(const T& o1, const T& o2) const {
return operator()(o1, o2, &get_quantity<T>);
}
};
(I've omitted the unnecessary boost::bind.) Also, you will need to declare myobj::qty to be const:
int qty() const {
return qty_;
}
since you want to invoke it on const objects. (Live demo)
For example:
struct B{};
struct A {
const B& findB() const { /* some non trivial code */ }
// B& findB() { /* the same non trivial code */ }
B& findB() {
const A& a = *this;
const B& b = a.findB();
return const_cast<B&>(b);
}
};
The thing is I want to avoid repeating the same logic inside the constant findB and non-constant findB member function.
Yes, you can cast the object to const, call the const version, then cast the result to non-const:
return const_cast<B&>(static_cast<const A*>(this)->findB());
Casting away const is safe only when the object in question was not originally declared const. Since you are in a non-const member function, you can know this to be the case, but it depends on the implementation. Consider:
class A {
public:
A(int value) : value(value) {}
// Safe: const int -> const int&
const int& get() const {
return value;
}
// Clearly unsafe: const int -> int&
int& get() {
return const_cast<int&>(static_cast<const A*>(this)->get());
}
private:
const int value;
};
Generally speaking, my member functions are short, so the repetition is tolerable. You can sometimes factor the implementation into a private template member function and call that from both versions.
I think, that using cast here is ok, but if you definitely want to avoid it, you can use some template magic:
struct B
{
B(const B&)
{
std::cout << "oops I copied";
}
B(){}
};
struct A {
public:
A(){}
A(const A&){ std::cout << "a is copied:(\n";}
const B& findB() const { return getter(*this); }
B& findB() { return getter(*this); }
private:
template <typename T, typename V>
struct same_const
{
typedef V& type;
};
template <typename T, typename V>
struct same_const<const T, V>
{
typedef const V& type;
};
template <typename T>
static typename same_const<T,B>::type getter(T& t) { return t.b;}
B b;
};
int main()
{
A a;
const A a_const;
const B& b1 = a.findB();
B& b2 = a.findB();
const B& b3 = a_const.findB();
//B& b4 = a_const.findB();
}
If I want to create a function template, where the template parameter isn't used in the argument list, I can do it thusly:
template<T>
T myFunction()
{
//return some T
}
But the invocation must specify the 'T' to use, as the compiler doesn't know how to work it out.
myFunction<int>();
But, suppose I wanted to do something similar, but for the '[]' operator.
template
T SomeObject::operator [ unsigned int ]
{
//Return some T
}
Is there any way to invoke this operator?
This doesn't appear valid:
SomeObject a;
a<int>[3];
This should work:
class C
{
public:
template <class T>
T operator[](int n)
{
return T();
}
};
void foo()
{
C c;
int x = c.operator[]<int>(0);
}
But it's of no real value because you'd always have to specify the type, and so it looks like a very ugly function call - the point of an operator overload is to look like an operator invocation.
Boost.Program_options uses this neat syntax:
int& i = a["option"].as<int>();
Which is achieved with something like this:
class variable_value
{
public:
variable_value(const boost::any& value) : m_value(value) {}
template<class T>
const T& as() const {
return boost::any_cast<const T&>(m_value);
}
template<class T>
T& as() {
return boost::any_cast<T&>(m_value);
}
private:
boost::any m_value;
};
class variables_map
{
public:
const variable_value& operator[](const std::string& name) const
{
return m_variables[name];
}
variable_value& operator[](const std::string& name)
{
return m_variables[name];
}
private:
std::map<std::string, variable_value> m_variables;
};
You could adapt this idea to suit your own needs.
Like with any operator, the function name is operator#, so:
a.operator[]<int>(3);
You can use a.operator[]<int>(1);
But why do you want this?
This may not be an optimal solution, but you could directly call the operator as such:
a.operator[](3);
I tried this in g++ with the following test:
class MyClass {
public:
template<class T>
T operator[](unsigned int) {
// do something
return T();
}
};
int main(int argc, char* argv[]) {
MyClass test;
test.operator[]<int>(0);
//test<int>[0]; // doesn't compile, as you mentioned
return 0;
}
If you need to define operator[] then probably define the template at the class level. Something like this:
template<class T>
class C
{
public:
T operator[](int n)
{
return T();
}
};
int main()
{
C<int> c;
int x = c[0];
return 0;
}
I have a hard time coming up with an example where this would be needed (couldn't you just overload the operator instead?), but here's my thoughts anyway:
Since you cannot use the infix operator syntax with templatized operators, you might want to do the template instantiation before you call the operator. A proxy might be a way to do this.
class some_class {
private:
template<class T> class proxy {
some_class* that_;
public:
proxy(some_class* that) : that_(that) {}
T& operator[](std::size_type idx) {return that->get<T>(idx);}
};
template<class T> class const_proxy {
some_class* that_;
public:
proxy(const some_class* that) : that_(that) {}
const T& operator[](std::size_type idx) const {return that->get<T>(idx);}
};
template< typename T > proxy<T> get_array() {return proxy<T>(this);}
template< typename T > const_proxy<T> get_array() const {return proxy<T>(this);}
template< typename T > T& get(std::size_t idx) {/* whatever */}
template< typename T > const T& get(std::size_t idx) const {/* whatever */}
};
// This is a lousy use case.
// Did I already say I have a hard time imagining how to use this?
template< typename T >
void f(some_class& some_object, sid::size_t idx)
{
T& = some_object.get_array<T>()[idx];
}