I'd like to do the following:
class Foo {
protected:
template<Param>
void operator()(const Param& param) {
// stuff involving some RTTI magic
}
public:
void operator()(const A& param) should be operator()<A>;
void operator()(const B& param) should be operator()<B>;
}
Basically, I have a generic operator() that takes a generic template parameter. But, I only want to publish specific specializations for type safety.
Thanks!
Just give the private function a different name:
class Foo
{
private:
template <typename T> void foo(const T &);
public:
void operator()(const A & x) { foo(x); }
void operator()(const B & x) { foo(x); }
};
Related
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.
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.
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)
how do I provide extra member function for specialized template in a non-inline way?
i.e.
template<typename T>
class sets
{
void insert(const int& key, const T& val);
};
template<>
class sets<bool>
{
void insert(const int& key, const bool& val);
void insert(const int& key){ insert(key, true); };
};
But when I write sets<bool>::insert(const int& key) as
template<>
class sets<bool>
{
void insert(const int& key, const bool& val);
void insert(const int& key);
};
template<>
void sets<bool>::insert(const int& key)
{
insert(key, true);
}
GCC complains:
template-id ‘insert<>’ for ‘void
ip_set::insert(const int&)’ does
not match any template declaration
Besides what Effo said, if you want to add additional functionality in specializations you should move common functionality into a base template class. E.g.:
template<typename T>
class Base
{
public:
void insert(const int& key, const T& val)
{ map_.insert(std::make_pair(key, val)); }
private:
std::map<int, T> map_;
};
template<typename T>
class Wrapper : public Base<T> {};
template<>
class Wrapper<bool> : public Base<bool>
{
public:
using Base<bool>::insert;
void insert(const int& key);
};
void Wrapper<bool>::insert(const int& key)
{ insert(key, true); }
That's because it is not a function of your template so don't use "template<>". It works for me after removing "template<>" as below:
void sets<bool>::insert(const int& key)
{
insert(key, true);
}
My system FC9 x86_64.
The entire code:
template<typename T>
class sets
{
public:
void insert(const int& key, const T& val);
};
template<>
class sets<bool>
{
public:
void insert(const int& key, const bool& val) {}
void insert(const int& key);
};
void sets<bool>::insert(const int& key)
{
insert(key, true);
}
int main(int argc, char **argv)
{
sets<bool> ip_sets;
int key = 10;
ip_sets.insert(key);
return 0;
}
i think you should understand the following two points :
if the you want to specilize the class primary template, you must put the 'template<>' before the specilized edition declaration.but as for the member function, you needn't put the 'template<...>' before the member function definition(because the type info of the specilized template class has been set by you).
i don't think the primary template class has ant thing to do with the specilized edition.
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];
}