I am relatively new to C++11, though I have used previous versions for many years.
Is this the correct way to enforce that an object will only be movable?
class CResource
{
public:
CResource();
CResource(CResource &&);
CResource & operator=(CResource &&);
private:
CResource(const CResource &) = delete;
CResource & operator=(const CResource &) = delete;
void * m_pResource;
};
class CAcquireResource
{
public:
CResource && AcquireResource();
};
CResource && CAcquireResource::AcquireResource()
{
CResource res;
return std::move(res);
}
Edited after comments from Sebastian Redl and underscore_d
class CResource
{
public:
CResource();
CResource(CResource &&);
CResource & operator=(CResource &&);
};
class CAcquireResource
{
public:
CResource AcquireResource();
};
CResource CAcquireResource::AcquireResource()
{
CResource res;
return std::move(res);
}
Assertions are holding up aswell...
#include <type_traits>
#define STR_NAME(s) #s
#define STATIC_ASSERT_NOCOPYASSIGN(clazz) \
static_assert(!std::is_copy_assignable<clazz>::value, \
STR_NAME(clazz) " is_copy_assignable");
#define STATIC_ASSERT_NOCOPYCONSTRUCT(clazz) \
static_assert(!std::is_copy_constructible<clazz>::value, \
STR_NAME(clazz) " is_copy_constructible");
#define STATIC_ASSERT_MOVEASSIGN(clazz) \
static_assert(std::is_move_assignable<clazz>::value, \
STR_NAME(clazz) " !is_move_assignable");
#define STATIC_ASSERT_MOVECONSTRUCT(clazz) \
static_assert(std::is_move_constructible<clazz>::value, \
STR_NAME(clazz) " !is_move_constructible");
#define STATIC_ASSERT_REFERENCECLASS(clazz) \
STATIC_ASSERT_MOVEASSIGN(clazz) \
STATIC_ASSERT_MOVECONSTRUCT(clazz) \
STATIC_ASSERT_NOCOPYASSIGN(clazz) \
STATIC_ASSERT_NOCOPYCONSTRUCT(clazz)
STATIC_ASSERT_REFERENCECLASS(CResource);
These pass with Visual Studio 2017.
Your method enforces move-only.
However, the mere existence of a move constructor/assignment operator already suppresses the generation of copy constructor and assignment operator; no explicit deletion is necessary. Only a few compilers in the early days of C++11 drafts didn't correctly implement this part.
However, note that your AcquireResource code returns a reference to a local variable and thus has undefined behavior. You should return by value.
Related
After referred Qt Singleton implementation. I got two solutions:
The first, using template:
template <typename T>
class Singleton
{
friend T;
public:
static T& instance();
private:
Singleton() = default;
~Singleton() = default;
Singleton( const Singleton& ) = delete;
Singleton& operator=( const Singleton& ) = delete;
};
template <typename T>
T& Singleton<T>::instance()
{
static T inst;
return inst;
}
class SingletonTest : public Singleton<SingletonTest>
{
public:
void foo(){
qDebug()<<"FOO"<<this;
}
};
The second using macro:
#define SingletonClass(className) \
public: \
className(className const&) = delete; \
className& operator=(className const&) = delete; \
static className& instance() { \
static className instance; \
return instance; \
} \
private: \
className() = default; \
~className() = default;
class SingletonTest
{
SingletonClass(SingletonTest)
public:
void foo(){
qDebug()<<"FOO"<<this;
}
};
About the first one, it allows instance creation like SingletonTest t, as a Singleton class I think that should not be allowed.
Then I think about the second one, it solves the first problem, but it has to pass the class name into the macro.
So which implementation is better?
Anyway to avoid passing the class name?
Is that wrong to return pointer of instance() function?
Reading Scott Meyer's book "Effective Modern C++", Item 24 (and following), and Item 41, I wonder that this book opposes:
the individual constructors for lvalue and rvalue parameters
to
a template'd universal constructor solution
It says, that 1. has the disadvantage to duplicate code.
Whereas 2. has the disadvantage to potentially being used for unwanted types.
I wonder why the book does not mention a mixed model - as in the example code shown below.
It uses type-safe dedicated constructors for lvalue and rvalue but delegates to a single (private) generic implementation for "universal reference".
This avoids unwanted template types of a public "universal reference" constructor.
So is there is anything wrong with the approach below? Something I missed?
#include <iostream>
#include <string>
class MyClass
{
private:
enum class Dummy { Nop = 0 } ;
template <class T>
MyClass(Dummy, T&& data)
: _data(std::forward<T>(data))
{
std::cout << "MyClass universal reference template c'tor" << std::endl;
}
public:
// proxy c'tors delegating to universal reference c'tor
MyClass (std::string const & data)
: MyClass(Dummy::Nop, data)
{
std::cout << "MyClass lvalue c'tor" << std::endl;
}
MyClass (std::string && data)
: MyClass(Dummy::Nop, std::move(data))
{
std::cout << "MyClass rvalue c'tor" << std::endl;
}
private:
std::string _data;
};
int main(int, char**)
{
{
std::string str("demo");
MyClass myClass(str);
}
{
MyClass myClass("hello, world");
}
return 0;
}
And now let's put the book down and do it the right way:
Pros:
Optimal efficiency
Correct type limitations
DRY
Cons:
None
-
#include <iostream>
#include <string>
#include <type_traits>
class MyClass
{
public:
template <class T, std::enable_if_t<std::is_constructible<std::string, T>::value>* = nullptr>
MyClass(T&& data)
: _data(std::forward<T>(data))
{
std::cout << "MyClass universal reference template c'tor" << std::endl;
}
private:
std::string _data;
};
int main()
{
using namespace std::string_literals;
auto a = MyClass("hello"s);
auto b = MyClass("world");
const auto s = "Hello, World"s;
auto s2 = "Hello, World";
auto c = MyClass(s);
auto d = MyClass(s2);
// won't compile
// auto e = MyClass(10);
}
g++ 5.2.1 fails to compile when it encounters a private method's address in a template deduction context whereas clang 3.5 only discards the specialization.
g++ 5.2.1 can access protected members of parents/friends in a class template parameter list when clang 3.5 sometimes fail to do so.
Which are wrong in which cases?
More precisely:
Should the compiler cause a hard error when trying to access a non accessible protected/private member in a template deduction context? Am I doing something wrong in my first example?
If not, should the compiler discard a specialization when trying to access (in a template deduction context) a protected member owned by:
a base class of this specific specialization
a class which declared this specific instantiation as a friend
a friend class which declared any instantiation of this template as a friend
The first question seems to have already been answered here (and the answer seems to be "no, the code isn't ill-formed and the compiler should simply discard this specialization"). However, since it's a prerequisite to the second question (and g++ 5.2.1 doesn't seem to agree), I want to be absolutely sure that it's g++ 5.2.1 which is wrong, not me.
Longer version with examples
I would like to make traits able to detect whether some functions/methods are implemented, even if they are protected members of some class (if you find this odd, I'll explain why I want to do this at the end of this question so that you can tell me I'm completely wrong, should learn how to design my classes, and maybe suggest me a cleaner way to do so).
My problem is that each of my attempts fail on either clang or g++ (oddly enough, not both at the same time): Sometimes it compiles but don't provide the expected result, sometimes it doesn't compile at all.
Even though it seems it isn't practical, I at least want to know when the compilers are faulty, and when I'm writing ill-formed code. Hence this question.
I use the C++11 dialect, and my clang version is actually the compiler provided with XCode 5 i.e. Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn).
To better illustrate what my problem is, here is a minimal exemple where clang compiles but g++ 5.2.1 doesn't:
#include <iostream>
#include <type_traits>
#include <utility>
struct PrivateFoo {
private:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
template<class C, class = void>
struct has_foo : std::false_type {};
template<class C>
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
std::true_type {};
int main() {
std::cout << std::boolalpha;
std::cout << "PrivateFoo has foo: " << has_foo<PrivateFoo>::value << '\n';
return 0;
}
output with clang 3.5:
PrivateFoo has foo: false
g++ 5.2.1 errors:
access_traits.cpp : [in instantiation of] ‘struct has_foo<PrivateFoo>’ :
access_traits.cpp:37:61: required from here
access_traits.cpp:7:8: [error]: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:32:56: [error]: [in context]
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
^
access_traits.cpp:7:8: [error]: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:32:56: [error]: [in context]
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
^
access_traits.cpp: [in function] ‘int main()’:
access_traits.cpp:7:8: erreur: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:37:42: [error]: [in context]
std::cout << "PrivateFoo has foo: " << has_foo<PrivateFoo>::value << '\n';
(text in brackets is translated, it was originally in my native language)
Here is an example where both compile but disagree on whether foo is accessible or not:
#include <iostream>
#include <type_traits>
#include <utility>
struct ProtectedFoo {
protected:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class = void>
struct has_foo_helper : std::false_type {};
template<class C>
struct has_foo_helper<C, void_t<decltype(std::declval<C>().foo())>> :
std::true_type {};
}
template<class C>
struct has_public_or_protected_foo : protected C {
template<class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<has_public_or_protected_foo<C>>::value;
};
int main() {
std::cout << std::boolalpha;
std::cout << "ProtectedFoo has foo: ";
std::cout << has_public_or_protected_foo<ProtectedFoo>::value << '\n';
return 0;
}
output with clang 3.5:
ProtectedFoo has foo: false
output with g++ 5.2.1:
ProtectedFoo has foo: true
and finally here is an example where both compile and agree that they should be able to access foo:
#include <iostream>
#include <type_traits>
#include <utility>
struct ProtectedFoo {
protected:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class D, class = void>
struct has_foo_helper : std::false_type {};
template<class C, class D>
struct has_foo_helper<C, D, void_t<check_signature<void(C::*)(), &D::foo>>> :
std::true_type {};
}
template<class C>
struct has_public_or_protected_foo : protected C {
template<class, class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<C, has_public_or_protected_foo<C>>::value;
};
int main() {
std::cout << std::boolalpha;
std::cout << "ProtectedFoo has foo: ";
std::cout << has_public_or_protected_foo<ProtectedFoo>::value << '\n';
return 0;
}
output with clang 3.5:
ProtectedFoo has foo: true
output with g++ 5.2.1:
ProtectedFoo has foo: true
Also here is a more complete example which summarizes it all:
#include <iostream>
#include <type_traits>
#include <utility>
/* test classes */
struct PublicFoo {
void foo() {}
};
struct ProtectedFoo {
protected:
void foo() {}
};
struct PrivateFoo {
private:
void foo() {}
};
struct NoFoo {};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class D, class = void>
struct has_foo_helper : std::false_type {};
template<class C, class D>
struct has_foo_helper<C, D, void_t<check_signature<void(C::*)(), &D::foo>>> :
std::true_type {};
template<class C, class = void>
struct may_call_foo_helper : std::false_type {};
template<class C>
struct may_call_foo_helper<C, void_t<decltype(std::declval<C>().foo())>> :
std::true_type {};
}
template<class C>
struct has_foo : detail::has_foo_helper<C, C> {};
template<class C>
struct may_call_foo : detail::may_call_foo_helper<C> {};
template<class C>
struct has_protected_foo : protected C {
template<class, class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<C, has_protected_foo<C>>::value;
};
template<class C>
struct may_call_protected_foo : protected C {
template<class, class>
friend class detail::may_call_foo_helper;
static constexpr bool value =
detail::may_call_foo_helper<may_call_protected_foo<C>>::value;
};
/* test */
template<class T>
void print_info(const char* classname) {
std::cout << classname << "...\n";
// comment this if you want to compile with g++
//*
std::cout << "has a public method \"void foo()\": ";
std::cout << has_foo<T>::value << '\n';
std::cout << "has a public or protected method \"void foo()\": ";
std::cout << has_protected_foo<T>::value << '\n';
//*/
std::cout << "has a public method \"foo\" callable without any arguments: ";
std::cout << may_call_foo<T>::value << '\n';
std::cout << "has a public or protected method \"foo\" callable without any "
"arguments: ";
std::cout << may_call_protected_foo<T>::value << '\n';
std::cout << '\n';
}
int main() {
std::cout << std::boolalpha;
// both g++ 5.2.1 and clang 3.5 compile
print_info<PublicFoo>("PublicFoo");
// g++ 5.2.1 fails to compile has_foo, clang 3.5 compiles fine
print_info<ProtectedFoo>("ProtectedFoo");
// g++ 5.2.1 fails to compile, clang 3.5 compiles fine
print_info<PrivateFoo>("PrivateFoo");
// both g++ 5.2.1 and clang 3.5 compile
print_info<NoFoo>("NoFoo");
return 0;
}
Why do I want to do this?
Skip this if you don't want to know the details. I just wrote this in case you were either shocked by the idea of me trying to detect protected members and/or curious about why I asked this question.
I was writing some kind of iterator template classes built out of other iterators and I got tired of writing multiple specializations depending on whether these iterators meet some requirements (ForwardIterator, BidirectionalIterator, RandomAccessIterator... although my iterators actually meet some relaxed versions of these concepts, they are kind of "proxy iterators" but it's not really relevant here).
For instance, if I only use random access iterators, my new custom iterator could (and should) also be some kind of random access iterator, hence implement operator+=, operator+, operator-=, operator-, operator<, operator>, operator<= and operator>=. However, some of these operators can easily be deduced from others, and they should only be defined if all the iterator I use are random access iterators.
I finally thought I'd just make something to provide default implementations if available. However, I wasn't really fond of the std::allocator_traits way as it wouldn't be very handy and readable with iterators (plus, I wouldn't be able to use them with some standard utilities).
The design I finally choose consists in having a template class which will build a full-fledged iterator out of a minimal implementation (for instance containing only the operator+=, operator==, operator* and operator> definitions) by having an inheritance chain of "mixins" (whose ancestor is my minimal iterator) detecting whether the functions/methods they need are available in their base class and defining the default methods if they are.
There is a subtility though. Sometimes I want to return a reference to the final iterator (for instance in Iterator& operator++()). If it's a method I redefine, I can easily solve that with CRTP and a static_cast, but what if my mixins don't touch that method at all?
I figured I should probably forbid the use of any method I haven't touched and inherit my minimal iterator with the protected access specifier... but now then my traits fail to detect the availability of some protected methods.
Therefore, I'd like to have traits able to detect whether some members are available with either public or protected visibility.
I'm wanting to quickly implement what some call an "owner pointer", that is, a smart pointer ensuring unique ownership semantics, while providing "observer" pointers that don't keep the object alive, but can test whether it is.
The most straightforward way I'm trying to do it is to subclass std::shared_ptr, and disable its copy-construction so that no other pointer can actually share the object.
This is what I have for now :
#include <memory>
#include <iostream>
template <class T>
struct owner_ptr : public std::shared_ptr<T> {
// Import constructors
using std::shared_ptr<T>::shared_ptr;
// Disable copy-construction
owner_ptr(owner_ptr<T> const&) = delete;
// Failed attempt at forbidding what comes next
operator std::shared_ptr<T> const&() = delete;
};
struct Foo {
Foo() {
std::cout << "Hello Foo\n";
}
~Foo() {
std::cout << "G'bye Foo\n";
}
void talk() {
std::cout << "I'm talkin'\n";
}
};
owner_ptr<Foo> fooPtr(new Foo);
int main(int, char**) {
// This should not compile, but it does.
std::shared_ptr<Foo> sptr = fooPtr;
// Simple tests
fooPtr->talk();
(*fooPtr).talk();
// Confirmation that two pointers are sharing the object (it prints "2").
std::cout << sptr.use_count() << '\n';
}
I've been pulling my hair on this one. How do I forbid the copy-construction of a std::shared_ptr from my owner_ptr ? I'm not fond of inheriting privately and then importing everything from std::shared_ptr...
I don't think subclassing std::shared_ptr is the way to go. If you really wanted to do it properly I think you should implement it yourself including all the reference counting. Implementing a smart pointer is not actually that hard.
However, in most cases, if you just want something that meets your needs use composition.
I was curious about what you were trying to do, I'm not convinced it is a good idea but I had a go at implementing a OwnerPointer and ObserverPointer pair using composition:
#include <memory>
#include <iostream>
struct Foo {
Foo() {std::cout << "Hello Foo\n"; }
~Foo() { std::cout << "G'bye Foo\n"; }
void talk() { std::cout << "I'm talkin'\n"; }
};
template <class T>
class ObserverPointer; // Forward declaration.
template<class T>
class OwnerPointer; // Forward declaration.
// RAII object that can be obtained from ObserverPointer
// that ensures the ObserverPointer does not expire.
// Only operation is to test validity.
template <class T>
class ObserverLock {
friend ObserverPointer<T>;
private:
std::shared_ptr<T> impl_;
ObserverLock(const std::weak_ptr<T>& in) : impl_(in.lock()) {}
public:
// Movable.
ObserverLock(ObserverLock&&) = default;
ObserverLock& operator=(ObserverLock&&) = default;
// Not copyable.
ObserverLock& operator=(const ObserverLock&) = delete;
ObserverLock(const ObserverLock&) = delete;
// Test validity.
explicit operator bool() const noexcept { return impl_ != nullptr;}
};
template <class T>
class ObserverPointer {
private:
std::weak_ptr<T> impl_;
T* raw_;
public:
ObserverPointer(const OwnerPointer<T>& own) noexcept : impl_(own.impl_), raw_(own.get()) {}
T* get() const { return raw_; }
T* operator->() const { return raw_; }
T& operator*() const { return *raw_; }
ObserverPointer() : impl_(), raw_(nullptr) { }
ObserverPointer(const ObserverPointer& in) = default;
ObserverPointer(ObserverPointer&& in) = default;
ObserverPointer& operator=(const ObserverPointer& in) = default;
ObserverPointer& operator=(ObserverPointer&& in) = default;
bool expired() { return impl_.expired(); }
ObserverLock<T> lock() { return ObserverLock<T>(impl_); }
};
template <class T>
struct OwnerPointer {
friend ObserverPointer<T>;
private:
std::shared_ptr<T> impl_;
public:
// Constructors
explicit OwnerPointer(T* in) : impl_(in) {}
template<class Deleter>
OwnerPointer(std::unique_ptr<T, Deleter>&& in) : impl_(std::move(in)) { }
OwnerPointer(std::shared_ptr<T>&& in) noexcept : impl_(std::move(in)) { }
OwnerPointer(OwnerPointer<T>&&) noexcept = default;
OwnerPointer(OwnerPointer<T> const&) = delete;
// Assignment operators
OwnerPointer& operator=(OwnerPointer<T> const&) = delete;
OwnerPointer& operator=(OwnerPointer<T>&&) = default;
T* get() const { return impl_.get(); }
T* operator->() const { return impl_.get(); }
T& operator*() const { return *impl_; }
explicit operator ObserverPointer<T>() const noexcept { return ObserverPointer<T>(impl_);}
explicit operator bool() const noexcept { return impl_;}
};
// Convenience function equivalent to make_shared
template <class T, class... Args>
OwnerPointer<T> make_owner(Args && ...args) {
return OwnerPointer<T>(new T(std::forward<Args>(args)...));
}
int main() {
auto owner = make_owner<Foo>();
ObserverPointer<Foo> observer = owner;
auto lock = observer.lock();
if (lock)
observer->talk();
}
Live demo.
It probably needs some work and it doesn't offer the full feature set of std::shared_ptr & std::weak_ptr but then in most cases it won't need to, just create what you need.
I've stretched the definition of "unique ownership" by offering an RAII ObserverLock object that can only be used to keep the ObserverPointer alive. Technically it "owns" the pointer but it is very restricted in what it can do and you can't create more than one "OwnerPointer".
I wanted to store a vector of function pointers, each taking different no. of arguments in a class "Store". So, wrote a templated class "Func" that would store the function as a std::function and its arguments in a tuple.
I derived this "Func" class from a non-template base class "IFunc", so that i can store a vector of pointers to this base class in the class "Store".
template<typename... Args>
class Func : public IFunc
{
public:
std::function<void (Args...)> f;
std::tuple<Args...> args;
template <typename F,typename... Ar>
Func(F&& func,Ar&&... arg): f(std::forward<F>(func)),args(std::make_tuple(std::forward<Ar>(arg)...))
{
}
virtual ~NonMemfun()
{
}
//other methods to unpack the tuple and call the function
};
The IFunc class:
class IFunc
{
public:
Ifunc(){}
virtual ~Ifunc(){}
};
The Store class:
class Store
{
std::vector<Ifunc*> funcs;
public:
template<typename... Args,typename... Args2>
void registerfunc(std::string name,int runs,void(*f)(Args...),Args2&&... arg)
{
Func<Args2...>* sample = new Func<Args2...>(f,arg...);
Ifunc* fp = sample;
funcs.push_back(fp);
}
};
I want to iterate through the vector and call each function. To do that i need to do a static cast like this:
Func<>* der = static_cast<Func<>*>(funcs[0]);
When i try to do this, the cast doesn't happen properly. I cannot specify the template paramenters(variadics) since this class(Store) is not aware of them.
I am totally stuck at this place. Something is wrong with my design i guess. Can someone please suggest me a better way to do this. Thank you.
Rather than trying to do a cast from IFunc to Func<>, you should make a pure virtual function, Apply() in IFunc, which Func<> defines as apply(f, args...);. As you iterate over the vector of IFunc pointers, simply call IFunc->Apply(), which will dispatch to the Func<>::Apply() and do the actual apply.
I'm not much of a C++ programmer, but I think you may find this useful.
I'm sure you know that templates are a compile time thing in C++ so your functions need to be known at build time.
With that said, if you do know your functions and you just want to map them to say a string command and then dynamically bind arguments from something like a stream then this code should help you. It is actually able to use a dynamic_cast to retrieve the command from the map.
this snippet is from a school project I did a while back that had a similar goal:
#include <map>
#include <string>
#include <sstream>
#include <tuple>
using namespace std;
class Shell {
class Command {
public:
virtual ~Command() {};
virtual void executeWithArgStream(Shell*, istream& s)=0;
};
template <typename... ArgTypes>
class ShellCommand : public Command {
private:
// FIXME: its probably more apropriate for FuncType to return an int for exit code...
typedef function<void(Shell*, ArgTypes...)> FuncType;
FuncType _f;
tuple<ArgTypes...> args;
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { typedef seq<Is...> type; };
template<size_t I = 0, class ...P>
typename std::enable_if<I == sizeof...(P)>::type
// template for functions with no arguments
parseArgs(istream& is, std::tuple<P...> &) {}
template<size_t I = 0, class ...P>
typename std::enable_if<I < sizeof...(P)>::type
parseArgs(istream& is, std::tuple<P...> & parts) {
// this is the magic bit that takes a tuple of pointers (representing the command arguments)
// created at compile time and creates new instances of each argument type and populates it from
// the given input stream :D
auto& part = std::get<I>(args);
// hmmm should we delete or recycle...
delete part;
part = new typeof(*part);
is >> *part;
parseArgs<I + 1>(is, parts);
}
template<int ...S>
void callFunc(Shell* shell, seq<S...>) {
_f(shell, get<S>(args) ...);
}
public:
static constexpr size_t numArgs = sizeof...(ArgTypes);
ShellCommand(FuncType f) : _f(f) {};
void operator()(Shell* shell, ArgTypes... args) {
_f(shell, args...);
};
void executeWithArgStream(Shell* shell, istream& s)
{
parseArgs(s, args);
callFunc(shell, typename gen_seq<sizeof...(ArgTypes)>::type());
};
};
private:
typedef shared_ptr<Command> CommandPtr;
typedef map<string, CommandPtr> FMap;
FMap _cmdMap;
ostream& _out;
istream& _in;
public:
Shell(istream& is = cin, ostream& os = cout)
: _out(os), _in(is)
{
// populate
_cmdMap.insert(pair<string, CommandPtr>("chdir", make_shared<ShellCommand<string*>>(&Shell::chdir)));
_cmdMap.insert(pair<string, CommandPtr>("list", make_shared<ShellCommand<>>(&Shell::list)));
_cmdMap.insert(pair<string, CommandPtr>("count", make_shared<ShellCommand<>>(&Shell::count)));
};
int run();
// FIXME: its probably more apropriate for execute to return an int for exit code...
template <typename... ArgTypes>
void execute(string& command, ArgTypes... args);
void executeWithArgStream(string& command, istream& istr);
// shell commands:
// any command parameters must be done as a pointer!
// the magic that parses string arguments into real types depends on it!
void list() {
list command
};
void chdir(string* dir) {
// chdir command
};
void count() {
// count command
};
};
template <typename... ArgTypes>
void Shell::execute(string& command, ArgTypes... args)
{
typedef ShellCommand<ArgTypes...> CommandType;
CommandType* c = dynamic_cast<CommandType*>(_cmdMap[command].get());
// TODO: neeed to diferentiate between invalid commands and some kind of dynamic_cast failure
if (c) {
(*c)(this, args...);
} else {
// dynamic cast failure
throw runtime_error("Broken Implementation for:" + command);
}
}
void Shell::executeWithArgStream(string& command, istream& istr)
{
Command* c = _cmdMap[command].get();
if (c) {
c->executeWithArgStream(this, istr);
} else {
throw runtime_error("Invalid Shell Command: " + command);
}
}
int Shell::run()
{
do {
string cmd, argString;
_out << _currentDir->name() << "> ";
_in.clear();
_in >> cmd;
if (cmd == "q") {
return 0;
}
if (_in.peek() == ' ')
_in.ignore(1, ' ');
getline(cin, argString);
if (_cmdMap[cmd]) {
try {
if (argString.length()) {
istringstream s(argString);
executeWithArgStream(cmd, s);
} else {
execute(cmd);
}
} catch (runtime_error& e) {
_out << e.what() << endl;
}
} else {
_out << "unrecognized command: " << cmd << endl;
}
} while (true);
}
int main(int argc, const char * argv[])
{
// start the interactive "shell"
Shell shell();
return shell.run();
}