Look at this code.
#include <vector>
template<class ...Args>
using other_vector = std::vector<Args...>;
template<class T>
void f(std::vector<T>& ) {}
template<class T>
void f(other_vector<T>& ) {}
int main()
{
other_vector<int> b;
f(b);
return 0;
}
It does not compile, because f is being redeclared. I totally understand the error. However, I need a second class that behaves like std::vector<T>, but will be seen as a different type, so that overloading, like in the above example, would be legal.
What could I do?
Let the new class have std::vector<T> as a base class. This might work, but one should not inherit from std containers.
Let the new class have a member of type std::vector and then redeclare all functions to redirect to the functions of the member. Sounds like a lot of work.
Any better alternative? C++11 or C++14 allowed.
You might try to mess with the allocator:
template<class T>
struct allocator_wrapper : T { using T::T; };
template<class T, class A = std::allocator<T>>
using other_vector = std::vector<T, allocator_wrapper<A>>;
Live example
If you need more than one copy, you can make it a template and take an int template arg for "clone number"
You may wrap your type as follow:
// N allow to have several 'version' of the same type T
template <typename T, int N = 0>
class WrapperType
{
public:
WrapperType() = default;
WrapperType(const WrapperType&) = default;
WrapperType(WrapperType&&) = default;
template <typename ... Ts>
explicit WrapperType(Ts&& ... ts) : t(std::forward<Ts>(ts)...) {}
// implicit conversion
// you may prefer make them explicit or use name get().
operator const T& () const { return t; }
operator T& () { return t; }
private:
T t;
};
And so for your case:
template<class T>
using other_vector = WrapperType<std::vector<T>>;
Related
Using C++ 17. I have the following:
template <typename T>
using ptr_t = std::shared_ptr<const T>;
class some_type;
class A { some_type foo() const; }
class B { some_type foo() const; }
class C { some_type foo(int) const; }
std::variant<ptr_t<A>, ptr_t<B>, ptr_t<C>>;
A variant holds shared_ptr(s) to different types. All expected to have function foo() that may be void or take a parameter. I will then have a visitor that would correctly dispatch foo, something like this (conceptually):
struct visitor
{
template <typename T>
ptr_t<some_type> operator()(const T& config) const
{
if constexpr (// determine if foo() of the underlying type of a shared_ptr can be called with int param)
return config->foo(15);
else
return config->foo();
}
is there a way to say this? I tried various ways but can't come with something that compiles. Template parameter, T, is ptr_t<A|B|C>.
std::is_invocable_v<Callable, Args...> is the way to go. Unfortunatelly, it will not compile just like that with if constexpr. It will either fail because "there is no operator()() overload", or there is no overload for operator taking Args....
I suggest you add a wrapper class for a callable and use it with a specialized alias template of std::variant instead of writing your own visitor. It will allow you to use std::visit seamlessly.
#include <type_traits>
#include <variant>
template <typename Callable>
class wrapped_callable
{
Callable c;
public:
wrapped_callable(Callable c)
: c(c)
{}
template <typename ... Args>
constexpr decltype(auto) operator()(Args &&... args) const
{
return _invoke(std::is_invocable<Callable, Args...>{}, c, std::forward<Args>(args)...);
}
private:
using _invocable = std::true_type;
using _non_invocable = std::false_type;
template <typename T, typename ... Args>
constexpr static decltype(auto) _invoke(_invocable, const T& t, Args &&... args)
{
return t(std::forward<Args>(args)...);
}
template <typename T, typename ... Args>
constexpr static decltype(auto) _invoke(_non_invocable, const T& t, Args ... args)
{
return t();
}
};
template <typename ... T>
using variant_callable = std::variant<wrapped_callable<T>...>;
struct int_callable
{
int operator()(int i) const
{
return i;
}
};
struct non_callable
{
int operator()() const
{
return 42;
}
};
#include <iostream>
int main()
{
using variant_t = variant_callable<int_callable, non_callable>;
// 23 is ignored, 42 is printed
std::visit([](const auto &callable){
std::cout << callable(23) << '\n';
}, variant_t{non_callable()});
// 23 is passed along and printed
std::visit([](const auto &callable){
std::cout << callable(23) << '\n';
}, variant_t{int_callable()});
}
Program returned: 0
42
23
https://godbolt.org/z/e6GzvW6n6
But The idea is not to have any specialization for all types in a variant as it will then require changing the visitor code every time a new type is added.
That is what template alias of std::variant<wrapped_callable<T>...> for. You just add append a new type to the list, that's it.
Take notice, that it does not depend on if constexpr. So if you manage to provide your own variant and is_invocable_v, it will work for C++14. For C++11 possibly, but some modifications regarding constexpr functions might be needed.
Of course you can implement your visitor in the same manner if you want to use std::shared_ptr istead of a callable.
But I don't see any reason to use:
visitor + smart pointer. Just use a smart pointer - it will give you runtime polymorphism in a "classic" way (via virtual inheritence)
why std::shared_ptr? Do you really need to share the ownership? Just stick with std::unique_ptr
Let's say I have the following class:
template <typename T>
class SomeClass : Parent<T>
{
public:
// I have a function such as this one:
T DoSomething(const T &t)
{
return t.DoSomething(some_data);
}
// But `T` might be a pointer, so sometimes I will need something like the following
// instead (which obviously doesn't work as given):
T DoSomething(const T &t)
{
return new T(t->DoSomething(some_data));
}
private:
XYZ some_data;
};
I got stuck in a giant mess of template errors trying to implement this in any semi-nice way possible using template specialization.
In the end I came up with this very ugly solution:
template <typename T>
class SomeClass : Parent<T>
{
public:
T DoSomething(const T &x)
{
return Specializer<T>::Do(this, x);
}
private:
template <typename V>
struct Specializer {
static V Do(SomeClass *me, const V &x)
{
return x.DoSomething(me->some_data);
}
};
template <typename V>
struct Specializer<V*> {
static V* Do(SomeClass *me, const V *&x)
{
return new V(x->DoSomething(me->some_data));
}
};
XYZ some_data;
};
Is there a better way to do this that doesn't involve stuffing this function into a dummy class/struct and passing around my this pointer?
PS: In reality, this has nothing to do with pointers, but rather with different types of containers. Pointers were just an easy example to use here.
You can avoid writing any specializations, and use a type trait like std::is_pointer along with if constexpr to decide what code to execute depending on the whether the type is a pointer type or not:
auto DoSomething(const T &t)
{
if constexpr (std::is_pointer_v<T>)
return new T(t->DoSomething(some_data));
else
return t.DoSomething(some_data);
}
If you don't want to check for whether T is a pointer, but want to check something else, you can still use this pattern by dropping in a suitable replacement for is_pointer.
If you have access to c++20, you can clean up the need for any SFINAE, specializations, or if constexpr by using concepts and constraints instead. This just allows you to define the same function N times with different criteria for its insantiation, which is much more readable IMO.
This is almost the same as the SFINAE approach, but without the need for the awful syntax (no std::declval, decltype, etc). It also doesn't require all implementations to exist in one function definition like the if constexpr approach; all you need is separate function definitions with different requires clauses:
#include <concepts>
...
template <typename T>
class SomeClass : Parent<T>
{
public:
// Work for everything that's not specialized
void DoSomething(const T &t)
{
std::cout << "Basic overload" << std::endl;
}
// Only work for pointers
void DoSomething(const T& t) requires(std::is_pointer_v<T>)
{
std::cout << "Pointer overload" << std::endl;
}
// Only work if T is convertible to SomeType
void DoSomething(const T& t) requires(std::convertible_to<T, SomeType>)
{
std::cout << "Convertible to SomeType overload" << std::endl;
}
private:
XYZ some_data;
};
Live Example
In this approach there are 3 different entries:
The basic fallback for all templates
An implementation that works for any pointer type, and
An implementation that works for any T type that may be convertible to SomeType
What about using SFINAE?
For example
#include <utility>
#include <iostream>
template <typename>
struct Parent
{ };
using XYZ = int;
template <typename T>
class SomeClass : Parent<T>
{
public:
template <typename U = T>
auto DoSomething (T const & t)
-> decltype( std::declval<U>().DoSomething(std::declval<XYZ>()) )
{ std::cout << "ref\n"; return t.DoSomething(some_data); }
template <typename U = T>
auto DoSomething (T const & t)
-> std::remove_reference_t<
decltype( std::declval<U>()->DoSomething(std::declval<XYZ>()),
std::declval<T>() )>
{
using V = std::remove_reference_t<decltype(*t)>;
std::cout << "pnt\n"; return new V(t->DoSomething(some_data));
}
private:
XYZ some_data;
};
struct foo
{
foo (foo*) {}
foo () {}
foo DoSomething (int) const { return {}; }
} ;
int main()
{
SomeClass<foo> sc1;
SomeClass<foo*> sc2;
foo f;
sc1.DoSomething(f);
sc2.DoSomething(&f);
}
I mean: what about enabling the first version if, and only if, T is a type that supports a DoSomething(XYZ) method and enabling the second version if, and only if, T is a pointer of a type that supports a DoSomething(XYZ) method?
I was hoping CTAD would work for alias templates, but it does not.
I had an idea of using inheritance where derived class constructor is a forwarding one(does nothing beside calling base).
Is this ok solution?
Is there a better solution(my goal is that users do not have to specify types inside <>)?
#include <iostream>
#include <type_traits>
template<typename T, bool is_mutable>
struct Ptr{
using PtrT= std::conditional_t<is_mutable, T*, const T*>;
Ptr(PtrT p): p_(p)
{
}
PtrT Get(){
return p_;
}
PtrT p_;
};
// CTAD does not work
// template<typename T>
// using MutPtr = Ptr<T, true>;
template<typename T>
struct MutPtr : public Ptr<T, true>{
MutPtr(T* p): Ptr<T, true>(p){}
};
int main()
{
MutPtr mp(new int{47});
(*mp.Get())++;
std::cout << *mp.Get() << std::endl;
}
I am using latest MSVC/Clang so I am fine with C++20 only solutions(EDIT: if they are implemented in latest MSVC/Clang).
I want to make static function in singletone template class, that would be able to deduct types of template class.
The problem is, that calling static function from template class requires explicit type.
The only workaround that I've came up with was template function instead if template member function.
Here is an example. The problem is that foo4 part is not working
template <class T>
class Foo
{
private:
Foo() {}
Foo(const Foo&) = delete;
Foo& operator= (const Foo&) = delete;
public:
static auto& Instance()
{
static Foo foo{};
return foo;
}
template<class K> static
auto& DeductInstance(const K&)
{
static Foo<K> foo{};
return foo;
}
};
template<class K>
auto& DeductInstance(const K&)
{
return Foo<K>::Instance();
}
void main()
{
auto& foo1 = Foo<int>::Instance(); //OK
auto& foo2 = Foo<int>::Instance(); //OK (return same example as foo1)
auto& foo3 = DeductInstance(123); //OK
auto& foo4 = Foo::DeductInstance(123); //NOT WORKING
}
The syntax you're asking for is theorically possible using injected class names. That would make Foo:: resolve to a particular, unrelated Foo<x>::. Here's an example:
struct BaseFoo {
template<class K> static
auto& DeductInstance(const K&);
};
template <class T>
struct Foo {
static auto& Instance() {
static Foo foo{};
return foo;
}
};
template<>
struct Foo<void> : private BaseFoo {
using BaseFoo::DeductInstance;
};
template<typename K>
auto& BaseFoo::DeductInstance(const K&)
{
return Foo<K>::Instance();
}
using MakeFooAvailable = Foo<void>;
struct Dummy : MakeFooAvailable {
auto& bar() {
// Syntax working
return Foo::DeductInstance(234);
}
};
In the class Dummy, there's a injected class name for the base class Foo, resolving it to Foo<void>. Then, Foo<void> is making BaseFoo::DeductInstance available for name resolution in its scope.
I would advise not using this solution because it's a clever one. Clever generally mean surprising. Programmers don't expect seeing Foo as a non template when it is. The best solution I think would be:
auto& foo1 = Foo<int>::Instance(); //OK
The simpler, the better.
I have to admit that I dont understand completely what you are trying to do. However, you can do either of the following two:
struct foo {
template <typename T>
static T deduce(const T& t) {
return {};
}
};
template <typename T>
T deduce_free(const T& t) {
return {};
}
int main() {
auto x = foo::deduce(1);
auto y = deduce_free(1);
}
But you cannot call a method (whehter static or not) on some instance of bar<T> before you know what T is.
Things have changed a bit with C++17 which has class template argument deduction, though as far as I know this works for constructors, so you would still need a foo<int> first before you could call a foo<int>::deduce() I am too unexperienced with that to say something not wrong ;).
It's 2021 and we have CTAD, but I don't think it helps. I think this is very close to what you (and I!) want:
// A helper struct to provide Foo with a default template
// that isn't useful for instantiation:
struct DoNotInstantiate { DoNotInstantiate() = delete; };
template <class T = DoNotInstantiate>
class Foo
{
private:
Foo() {
static_assert(!std::is_same_v<T, DoNotInstantiate>, "You can't actually instantiate it with the default, it's just to make the static function work."); // Optional
}
// ...
public:
// ...
template<class K> static
auto& DeductInstance(const K&)
{
static Foo<K> foo{};
return foo;
}
};
So you can call Foo<>::DeduceInstance(bar);. You still have to write the <> but otherwise, it's perfect, I think.
If you don't want that and really want to be able to call a static on a template, naming just the template name, there's this:
template <template<typename ...> class FooType, typename T>
auto DeduceInstance(const T& x) {
return FooType<T>::DeduceInstance(x);
}
which lets you call DeduceInstance<Foo>(x) where Foo is just a template. But that feels round-about. I prefer Foo<>::DeduceInstance(x);.
It would be nice if CTAD let you write
template <class T>
Foo::DeductInstance(const T&) -> T&;
or maybe it would be
template <class T>
Foo::DeductInstance(const T&) -> Foo<T>::DeduceInstance(const T&);
or something similar, basically saying that if you use the template name without a type to call a static, use the argument list to dope out which template the caller was talking about.
So I have a tremendous number of template specializations of this template:
template <typename T> // Same
struct foo { // Same
using type_name = T; // Same
foo(const int base) : _base(base) {} // May take other parameters
void func(const T& param) {} // This function signature will be the same but body will differ
int _base; // Same but may have more members
}; // Same
So an example specialization would be:
template<>
struct foo<float> {
using type_name = T;
foo(const int base, const int child) : _base(base), _child(child) {}
void func(const T& param) { cout << param * _child << endl; }
int _base;
int _child;
};
Obviously this is a toy example and the body of _func will be more involved. But I think this expresses the idea. I can obviously make a macro to help with the boilerplate and put the implementation of the specialized version of the function in an implementation file.
But I was hoping that C++ provided me a way to do this without macros. Is there another way for me avoid writing the boilerplate over and over?
you can have multiple specialization for the function but not for the whole class
like this
#include <iostream>
#include <string>
template<typename T>
struct foo {
//common generic code
using type_name = T;
foo(const int base, const int child) : _base(base), _child(child) {}
void func(const T& param);
int _base;
int _child;
};
template<>
void foo<float>::func(const type_name&) {
//implementation
std::cout << "float" << std::endl;
}
template<>
void foo<int>::func(const type_name&) {
//implementation
std::cout << "int" << std::endl;
}
int main() {
foo<int> tint(0, 0);
foo<float> fint(0, 0);
tint.func(0);
fint.func(0);
}
You can use some light inheritance of data structs to help you separate the differences in member layout and constructor definitions from the main template.
//Define an internal aggregate type you can specialize for your various template parameters
template <typename T>
struct foo_data {
foo(const int base) : _base(base) {}
int _base;
};
//Then derive privately from the data struct (or publicly if you really desire)
template <typename T>
struct foo : private foo_data<T> {
using type_name = T;
using foo_data<T>::foo_data<T>; //Make the base class constructors visible
void func(const T& param); //Use member specialization as suggested by the other answer
};
I will leave it to you to decide if it is better this way or not, but the upshot is that all the common parts are completely separated from all the uncommon parts.
In a comment under another answer I erroneously described this as CRTP. It isn't and it doesn't have any of the drawbacks as CRTP.
If you really need to preserve standard layout, then you can simulate inheritance manually with explicit delegation and perfect forwarding.
template <typename T>
struct foo {
using type_name = T;
template <typename... Args>
foo(Args&&... args) : base_data_(std::forward<Args>(args)...) {}
void func(const T& param); //Use member specialization as suggested by the other answer
foo_data<T> base_data_;
};
One drawback is I don't think the delegating constructor will SFINAE properly as written, and it also eats noexcept specifiers and explicit. Fixing those issues(if required) is left as an exercise to the reader.
There is no nice way to avoid some redundancy in notation when implementing specializations of templated types. There are some techniques to avoid duplication of actual code, such as
Using a traits template to provide type-specific things
template<typename T>
struct foo_traits { ... }; // provide many specialisations
template<typename T> // no specialisations
struct foo
{
using traits = foo_traits<T>;
template<typename...Aars>
explicit foo(Args&&...args)
: data(std::forward<Args>(args)...) {}
int do_something_specific(T x)
{ return traits::do_something(data,x); }
private:
typename traits::data data;
};
a very similar approach is to use a specialized base class:
template<typename T>
struct foo_base { ... }; // provide many specialisations
template<typename T> // no specialisations
struct foo : foo_base<T>
{
using base = foo_base<T>;
template<typename...Aars>
explicit foo(int m, Args&&...args)
: base(std::forward<Args>(args)...)
, more_data(m) {}
int do_something_specific(T x)
{ return base::do_something(x,more_data); }
private:
int more_data;
};
The constructor of foo is a variadic template in order to allow the base class's constructor to take any number and type of arguments.
Of you can use a common base class and specialize the derived classes. This can be done with the Curiously recurring template pattern (CRTP)
template<typename Derived>
struct foo_base // no specializations
{
using type = typename Derived::type;
int do_something(type x)
{
auto result = static_cast<Derived*>(this)->specific_method(x);
return do_some_common_stuff(result);
}
protected:
foo_base(type x) : data(x) {}
type data;
private:
int do_some_common_stuff(type x)
{ /* ... */ }
};
template<typename T> // some specialisations
struct foo : foo_base<foo<T>>
{
using base = foo_base<foo>;
using type = T;
using common_type = typename base::common_type;
using base::do_something;
explicit foo(type x, type y)
: base(x), extra_data(y) {}
protected:
type specific_method(type x)
{ /* ... */ }
private:
type extra_data;
};
Note that foo_base is already a template (unlike the situation with ordinary polymorphism), so you can do a lot of specific stuff there already. Only things that are done differently (not merely with different types) need specializations of foo.
Finally, you can combine these approaches, for example traits classes with CRTP.
All these methods implement some type of static or compile-time polymorphism, rather than real or dynamic polymorphism: there are no virtual functions and hence no virtual table and no overhead for table look-up. It is all resolved at compile time.
This is usually done through inheritance - you put the immutable part into base class, and specialize the children.
I do not think you need an example for that, but let me know if you do.