Declare member function only on specific specialization of templated class - c++

I have a templated class to aid in compile time computation of physical quantities. It uses the extra template parameters (std::ratio) to ensure things like a Length can only be added to a Length, or that Area is a Length times a Length.
#include <ratio>
template <
typename Length = std::ratio<0>, // Meter
typename Mass = std::ratio<0>, // Kilogram
typename Time = std::ratio<0>, // Second
typename Current = std::ratio<0>, // Ampere
typename Temperature = std::ratio<0>, // Kelvin
typename Amount = std::ratio<0>, // Mole
typename Luminous = std::ratio<0> // Candela
>
class Quantity {
private:
double value;
public:
constexpr Quantity(double val) : value(val) {}
Quantity &operator+=(Quantity const &that) {
value += that.value;
return *this;
}
// ...
};
But sometimes I want to convert back to a simple double, for interfacing with other stuff.
I could add a member function for the templated class that returns the internal double - or enables implicit (or explicit) conversion to double when a double is needed.
constexpr double getValue() { return value; }
constexpr operator double() { return value; }
However, I really only want this implicit conversion to happen when the "dimensions" of the quantity are all 0 (all template parameters are 0).
I could just declare the same member functions and only define the specialization that I want. But that still declares that the conversion exists for types that I don't ever want to allow conversion from (you should divide by your desired units first). This makes my editor tell me it's ok but it won't link at compiletime.
Is there a way to declare member functions only on certain specializations?
Of note, I'm stuck on C++14 for now, otherwise I think an if constexpr could work...

No, if constexpr cannot be used to provide for conditional definition of class methods. if constexpr belongs in some method or a function, so that needs to be declared before anything can be done with if constexpr, and your goal is to not even declare it in the first place.
There is no way to directly instantiate a class method only for certain specializations or template instances, however there's a common approach that comes pretty close: simulate an overload resolution failure.
Here's a simplified example:
#include <type_traits>
#include <iostream>
template<typename T>
struct life {
template<typename=
typename std::enable_if<std::is_same<T,int>::value>::type>
constexpr int answer()
{
return 42;
}
};
int main()
{
life<int> of_brian;
std::cout << of_brian.answer() << std::endl; // Shows 42
life<double> of_black_night;
std::cout << of_black_night.answer() << std::endl; // Error
return 0;
}
The template class effectively implements answer() only for its int instance. gcc's error message, for attempting to invoke it from an undesirable instance of the template is:
error: no matching function for call to ‘life<double>::answer()’
which is a pretty close facsimile for "this doesn't exist, pal".
This is logically equivalent to what you're attempting to do with your template, the only difference is that you need to check a bunch of template parameters, instead of just one.

Related

Can static polymorphism (templates) be used despite type erasure?

Having returned relatively recently to C++ after decades of Java, I am currently struggling with a template-based approach to data conversion for instances where type erasure has been applied. Please bear with me, my nomenclature may still be off for C++-natives.
This is what I am trying to achieve:
Implement dynamic variables which are able to hold essentially any value type
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to hold variable instances in containers, independent of their value type
Convert between variable value and representation using conversion functions
Be able to introduce new representations just by providing new conversion functions
Constraints: use only C++-11 features if possible, no use of libraries like boost::any etc.
A rough sketch of this might look like this:
#include <iostream>
#include <vector>
void convert(const std::string &f, std::string &t) { t = f; }
void convert(const int &f, std::string &t) { t = std::to_string(f); }
void convert(const std::string &f, int &t) { t = std::stoi(f); }
void convert(const int &f, int &t) { t = f; }
struct Variable {
virtual void get(int &i) = 0;
virtual void get(std::string &s) = 0;
};
template <typename T> struct VariableImpl : Variable {
T value;
VariableImpl(const T &v) : value{v} {};
void get(int &i) { convert(value, i); };
void get(std::string &s) { convert(value, s); };
};
int main() {
VariableImpl<int> v1{42};
VariableImpl<std::string> v2{"1234"};
std::vector<Variable *> vars{&v1, &v2};
for (auto &v : vars) {
int i;
v->get(i);
std::string s;
v->get(s);
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
return 0;
}
The code does what it is supposed to do, but obvoiusly I would like to get rid of Variable::get(int/std::string/...) and instead template them, because otherwise every new representation requires a definition and an implementation with the latter being exactly the same as all the others.
I've played with various approaches so far, like virtual templated, methods, applying the CRDT with intermediate type, various forms of wrappers, yet in all of them I get bitten by the erased value type of VariableImpl. On one hand, I think there might not be a solution, because after type erasure, the compiler cannot possibly know what templated getters and converter calls it must generate. On the other hand I think i might be missing something really essential here and there should be a solution despite the constraints mentioned above.
This is a classical double dispatch problem. The usual solution to this problem is to have some kind of dispatcher class with multiple implementations of the function you want to dispatch (get in your case). This is called the visitor pattern. The well-known drawback of it is the dependency cycle it creates (each class in the hierarchy depends on all other classes in the hierarchy). Thus there's a need to revisit it each time a new type is added. No amount of template wizardry eliminates it.
You don't have a specialised Visitor class, your Variable serves as a Visitor of itself, but this is a minor detail.
Since you don't like this solution, there is another one. It uses a registry of functions populated at run time and keyed on type identification of their arguments. This is sometimes called "Acyclic Visitor".
Here's a half-baked C++11-friendly implementation for your case.
#include <map>
#include <vector>
#include <typeinfo>
#include <typeindex>
#include <utility>
#include <functional>
#include <string>
#include <stdexcept>
struct Variable
{
virtual void convertValue(Variable& to) const = 0;
virtual ~Variable() {};
virtual std::type_index getTypeIdx() const = 0;
template <typename K> K get() const;
static std::map<std::pair<std::type_index, std::type_index>,
std::function<void(const Variable&, Variable&)>>
conversionMap;
template <typename T, typename K>
static void registerConversion(K (*fn)(const T&));
};
template <typename T>
struct VariableImpl : Variable
{
T value;
VariableImpl(const T &v) : value{v} {};
VariableImpl() : value{} {}; // this is needed for a declaration of
// `VariableImpl<K> below
// It can be avoided but it is
// a story for another day
void convertValue(Variable& to) const override
{
auto typeIdxFrom = getTypeIdx();
auto typeIdxTo = to.getTypeIdx();
if (typeIdxFrom == typeIdxTo) // no conversion needed
{
dynamic_cast<VariableImpl<T>&>(to).value = value;
}
else
{
auto fcnIter = conversionMap.find({getTypeIdx(), to.getTypeIdx()});
if (fcnIter != conversionMap.end())
{
fcnIter->second(*this, to);
}
else
throw std::logic_error("no conversion");
}
}
std::type_index getTypeIdx() const override
{
return std::type_index(typeid(T));
}
};
template <typename K> K Variable::get() const
{
VariableImpl<K> vk;
convertValue(vk);
return vk.value;
}
template <typename T, typename K>
void Variable::registerConversion(K (*fn)(const T&))
{
// add a mutex if you ever spread this over multiple threads
conversionMap[{std::type_index(typeid(T)), std::type_index(typeid(K))}] =
[fn](const Variable& from, Variable& to) {
dynamic_cast<VariableImpl<K>&>(to).value =
fn(dynamic_cast<const VariableImpl<T>&>(from).value);
};
}
Now of course you need to call registerConversion e.g. at the beginning of main and pass it each conversion function.
Variable::registerConversion(int_to_string);
Variable::registerConversion(string_to_int);
This is not ideal, but hardly anything is ever ideal.
Having said all that, I would recommend you revisit your design. Do you really need all these conversions? Why not pick one representation and stick with it?
Implement dynamic variables which are able to hold essentially any value type
Be able to hold variable instances in containers, independent of their value type
These two requirements are quite challenging on its own. The class templates don't really encourage inheritance, and you already did the right thing to hold what you asked for: introduced a common base class for the class template, which you can later refer to in order to store pointers of the said type in a collection.
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to introduce new representations just by providing new conversion functions
This is where it breaks. Function templates assume common implementation for different types, while inheritance assumes different implementation for the same types.
You goal is to introduce different implementation for different types, and in order to make your requirements viable you have to switch to one of those two options instead (or put up with a number of functions for each case which you have already introduced yourself)
Edit:
One of the strategies you may employ to enforce inheritance approach is generalisation of the arguments to the extent where they can be used interchangeably by the abstract interface. E.g. you may wrap the converting arguments inside of a union like this:
struct Variable {
struct converter_type {
enum { INT, STRING } type;
union {
int* m_int;
std::string* m_string;
};
};
virtual void get(converter_type& var) = 0;
virtual ~Variable() = default;
};
And then take whatever part of it inside of the implementation:
void get(converter_type& var) override {
switch (var.type) {
case converter_type::INT:
convert(value, var.m_int);
break;
case converter_type::STRING:
convert(value, var.m_string);
break;
}
}
To be honest I don't think this is a less verbose approach compared to just having a number of functions for each type combination, but i think you got the idea that you can just wrap your arguments somehow to cement the abstract class interface.
Implement std::any. It is similar to boost::any.
Create a conversion dispatcher based off typeids. Store your any alongside the conversion dispatcher.
"new conversion functions" have to be passed to the dispatcher.
When asked to convert to a type, pass that typeid to the dispatcher.
So we start with these 3 types:
using any = std::any; // implement this
using converter = std::function<any(any const&)>;
using convert_table = std::map<std::type_index, converter>;
using convert_lookup = convert_table(*)();
template<class T>
convert_table& lookup_convert_table() {
static convert_table t;
return t;
}
struct converter_any: any {
template<class T,
typename std::enable_if<
!std::is_same<typename std::decay<T>::type, converter_any>::value, bool
>::type = true
>
converter_any( T&& t ):
any(std::forward<T>(t)),
table(&lookup_convert_table<typename std::decay<T>::type>())
{}
converter_any(converter_any const&)=default;
converter_any(converter_any &&)=default;
converter_any& operator=(converter_any const&)=default;
converter_any& operator=(converter_any&&)=default;
~converter_any()=default;
converter_any()=default;
convert_table const* table = nullptr;
template<class U>
U convert_to() const {
if (!table)
throw 1; // make a better exception than int
auto it = table->find(typeid(U));
if (it == table->end())
throw 2; // make a better exception than int
any const& self = *this;
return any_cast<U>((it->second)(self));
}
};
template<class Dest, class Src>
bool add_converter_to_table( Dest(*f)(Src const&) ) {
lookup_convert_table<Src>()[typeid(Dest)] = [f](any const& s)->any {
Src src = std::any_cast<Src>(s);
auto r = f(src);
return r;
};
return true;
}
now your code looks like:
const bool bStringRegistered =
add_converter_to_table(+[](std::string const& f)->std::string{ return f; })
&& add_converter_to_table(+[](std::string const& f)->int{ return std::stoi(f); });
const bool bIntRegistered =
add_converter_to_table(+[](int const& i)->int{ return i; })
&& add_converter_to_table(+[](int const& i)->std::string{ return std::to_string(i); });
int main() {
converter_any v1{42};
converter_any v2{std::string("1234")};
std::vector<converter_any> vars{v1, v2}; // copies!
for (auto &v : vars) {
int i = v.convert_to<int>();
std::string s = v.convert_to<std::string>();
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
}
live example.
...
Ok, what did I do?
I used any to be a smart void* that can store anything. Rewriting this is a bad idea, use someone else's implementation.
Then, I augmented it with a manually written virtual function table. Which table I add is determined by the constructor of my converter_any; here, I know the type stored, so I can store the right table.
Typically when using this technique, I'd know what functions are in there. For your implementation we do not; so the table is a map from the type id of the destination, to a conversion function.
The conversion function takes anys and returns anys -- again, don't repeat this work. And now it has a fixed signature.
To add support for a type, you independently register conversion functions. Here, my conversion function registration helper deduces the from type (to determine which table to register it in) and the destination type (to determine which entry in the table), and then automatically writes the any boxing/unboxing code for you.
...
At a higher level, what I'm doing is writing my own type erasure and object model. C++ has enough power that you can write your own object models, and when you want features that the default object model doesn't solve, well, roll a new object model.
Second, I'm using value types. A Java programmer isn't used to value types having polymorphic behavior, but much of C++ works much better if you write your code using value types.
So my converter_any is a polymorphic value type. You can store copies of them in vectors etc, and it just works.

Ensure class methods with C++20 concepts

I love the feature of Interfaces in Java, and was looking forward to the new C++20 standart, introducing concepts.
On a current project i will have multiple implementations for the same thing. The rest of the code should be unaffected by that and handel them all in a general "one fits all" way. Further, to help other people coding there own implementation of this exchangeable part, i would like to have a central place for the documentation, describing all needed parts.
I tried to get this working for some time now, but i keep one struggeling with the C++20 concepts. Since nothing really worked i discribe what i would like to have with a small example:
/* Should have a element type, like float, int, double, std::size_t,... */
template <typename Class>
concept HasElementType = requires {
typename Class::Element;
};
/* Central place for the documentation: in the concept.
* Since all relevant parts should be listed here, they can be documentated.
*/
template < typename Class, typename T>
concept HasFunctions = requires {
Class::Class(int); /* has constructor with int */
T Class::field; /* has field with name "field" of type T */
int Class::foo(T); /* has method foo, taking T, returning int */
T Class::bar(int); /* has method bar, taking int, returning T */
void Class::foobar(); /* has method foobar, taking void, returnung void */
};
/* put both togetter */
template <typename Cls>
concept MyInterface = HasElementType<Cls> && HasFunctions<Cls,typename Cls::Element>;
The above concept MyInterface should than ensure, that calling the function below via my_function<MyObject>() should work properly for different implementations MyObject ∈ {Implementaion1, Implementaion2,...}.
/* Some example function */
template<MyInterface MyObejct>
void my_function(){
using T = MyObejct::Element;
T t = 5;
MyObejct myObject(1);
T field = myObject.field;
int foo = myObject.foo(t);
T bar = myObject.bar(1);
myObject.foobar();
}
I have 3 questions regarding this:
Is it possible with concepts, to accomplish that?
Is this in a somewhat clean look possible? Since it should increase the readability via accessible documentation, it would not be usefull if the code for the concept is barely readable.
Are concepts in generall the right approche, or are there other/better ways to accomplish that?
Thanks, moro
You haved asked multiple things, so I answer one by one. First your "HasElement" concept.
Here you can see how it works:
#include <iostream>
#include <type_traits>
class AWithStaticElement{
public:
static int Element;
};
int AWithStaticElement::Element = 12;
class AWithInstanceElement{
public:
int Element;
};
class AWithElementType{
public:
using Element = int;
};
class AWithoutElement{
};
template<typename T>
requires std::is_member_pointer_v<decltype(&T::Element)>
void Foo(T t)
{
std::cout << "Has instance Element " << t.Element << "\n";
}
template<typename T>
requires std::is_pointer_v<decltype(&T::Element)>
void Foo(T t)
{
std::cout << "Has static Element " << t.Element << "\n";
}
template<typename T>
requires requires (T t) { typename T::Element; }
void Foo(T t)
{
std::cout << "Has Element type\n";
}
template<typename... T>
void Foo(T&&... t)
{
std::cout << "Has no Element!\n";
}
int main()
{
Foo(AWithStaticElement{});
Foo(AWithInstanceElement{});
Foo(AWithElementType{});
Foo(AWithoutElement{});
}
With concepts you can basically give a set of requirements a name. If a concepts is long you don't need to repeat it all the time.
You have a plausible idea, but that's just not the syntax for requires-expressions. You want something like
template < typename Class >
concept HasFunctions = requires(Class c, Class::Element e) {
Class(1); // don't use a null pointer constant here!
{ c.field } -> std::same_as<decltype(e)>;
{ c.foo(e) } -> std::same_as<int>;
{ c.bar(1) } -> std::same_as<decltype(e)>;
c.foobar();
};
Note that there's no need to test Class::Element separately: if that type doesn't exist, then the atomic constraint simply evaluates to false as desired.
This isn't quite as strict as your phrasing suggests; it's sufficient that the class be constructible from an int (possibly via implicit conversions, default arguments, constructor templates, etc.), for example, and it ignores the return type of foobar entirely. However, as is rapidly becoming common advice for constraint authors, why do you care if foobar returns something? If you expect it to be void, you're not going to do much with the return value anyway. It's generally superior to require the interface that you will use (e.g., that you will pass an int here and ignore a value there) rather than trying to describe the implementation of the type in question. Accordingly, you might consider relaxing the std::same_as as well, perhaps with std::convertible_to.

How can I use type-safe unions (variants) inside a class with template functions?

I would like to place a std::variant inside a class and return its elements with a template function. Here is an example:
#include <string>
#include <variant>
class Class {
public:
std::variant<std::string, double> cont;
Class() {}
template <class V> Class(const V v) { cont = v; }
template <typename V> V fun() {
if (std::holds_alternative<double>(cont))
return std::get<double>(cont);
else if (std::holds_alternative<std::string>(cont))
return std::get<std::string>(cont);
}
};
int main() {
Class c;
c = 20;
double d = c.fun<double>();
return 0;
}
I try to return the elements of the class Class through the template function fun. However, gcc-9.1 refuses to compile the code and tells me
Class.cpp:12:46: error: cannot convert ‘std::__cxx11::basic_string<char>’ to ‘double’ in return
12 | return std::get<std::string>(cont);
Why is there any attempt to convert the string (the second return type of the function foo) to a double? Can I prevent this and solve the problem? Do I use the std::variant class unidiomatic?
The issue here is that you query the current value stored at runtime, while the function signature of the template instantiation is performed at compile time. Consider how the member function looks like when you try using it to retrieve a double:
double fun() {
if (/* ... */)
return std::get<double>(cont); // Ok return type is double, too
else if (/* ... */)
return std::get<std::string>(cont); // Error, return type should be string?!
}
This can't work. You need to change the way to access the data member, e.g. passing an overload set to std::visit, by providing two getter-like functions returning std::optional<double> and std::optional<std::string> or something similar.
All runtime if branches must be compilable even if not taken. If we call fun() with V == double then returning an std::string makes no sense and causes the error (even if that branch would never be taken, the compiler can't know that for certain).
Instead, just return it right away through V:
template <typename V> V fun() {
if (std::holds_alternative<V>(cont))
return std::get<V>(cont);
return {}; // return default constructed V. You could throw an exception here instead etc.
}

Saving class instances with different template parameters inside one vector but keep their properties

I would like to have a program that parses and manages command-line parameters for me. As you can see in the main-function, by using simple commands like Option<int>("number", { "-n", "--number" }) you can specify the type the option's value should have (like int in this case), an unique identifier for each option (like "number"), and multiple strings this option can be introduced with. Also, many options should be wrapped in a class called OptionSet, which simplifies access to its options.
But in my actual code, I am having several problems right now:
I want to store multiple instances of one class with different template parameters within one std::vector. For example, in my code, Option<int> should be stored in the same vector like Option<std::string> and Option<double>.
Maybe it's even possible to store the template parameters separately in another vector?
By using using, std::enable_if_t and std::is_same I created a type called OptionHasValue. If the template parameter Invert is false and T is void, OptionHasValue has an invalid type, otherwise it has the type specified by the template parameter U.
The class OptionValue uses OptionHasValue and a bit of SFINAE magic to decide if it should have the needed methods for supporting the storage of values or not. That is, the first version of OptionValue has OptionHasValue<T> as its second template parameter, so it becomes invalid (and removed by the compiler) if T is void. The other version of OptionValue has the opposite behavior, because its second template parameter is OptionHasValue<T, true> and the true inverts the behavior of OptionHasValue.
The class Option itself inherits from OptionValue, so if you create an option like Option<void>, it does not have support for values (that is, it lacks functions like setValue, setValueFromString and getValue as it should). On the other hand, if you create an option like Option<int>, the resulting class instance has all of these features.
The problem now is, that (for example) OptionSet::process() accesses both Option::hasValue and Option::setValueFromString, but the latter is only declared if Option::hasValue is true (and the corresponding template parameter for the option is not void). But because Option::setValueFromString is not wrapped in some kind of template here, the compiler also complains.
In my main-function I use the function optionSet.getOptionValue(std::string). This function should return the value of an option (after it has been set after process() has been called). The difficult thing now is that the return type depends on the return value of findOptionByIdentifier, a function which loops through all available options and returns the option with the wanted identifier.
For example, if identifier would be "number" (as in the example for an Option at the beginning of this question), the return type of findOptionByIdentifier would be Option<int>, because the only option having the identifier "number" is the one which has int as its first template parameter, which would finally result in getOptionValue having the return type int.
You can see the expected behavior in comments in some of the last lines of the main-function.
So, what do I have to change in the following code to fix all these things (and to make it compile)? I am using g++ 5.2.0 (mingw-w64), so I may use any feature of C++11 and C++14.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <type_traits>
#include <boost/lexical_cast.hpp>
#include <boost/any.hpp>
template<typename T, bool Invert = false, typename U = void>
using OptionHasValue = std::enable_if_t<(!std::is_same<T, void>::value) ^ Invert, U>; //only make this template substitution successful, if (when 'Invert' is false) T is not if type 'void'
template<typename T, typename Enable = void>
class OptionValue;
template<typename T>
class OptionValue<T, OptionHasValue<T>> //using SFINAE ("substitution failure is not an error") here
{
protected:
T value;
public:
void setValue(T newValue)
{
value = newValue;
}
void setValueFromString(std::string newValueStr)
{
setValue(boost::lexical_cast<T>(newValueStr));
}
T getValue()
{
return value;
}
bool hasValue()
{
return true; //if this class variant is taken by the compiler, the 'Option' that will inherit from it will have a value
}
};
template<typename T>
class OptionValue<T, OptionHasValue<T, true>> //the opposite condition (the 'true' inverts it)
{
//option value is disabled, but to check if a value is available in the derived class, add a function for that (or should I not?)
public:
bool hasValue()
{
return false;
}
};
template<typename T>
class Option : public OptionValue<T>
{
private:
std::string identifier;
std::vector<std::string> variants;
public:
Option(std::string newIdentifier, std::vector<std::string> newVariants)
{
identifier = newIdentifier;
variants = newVariants;
}
bool hasVariant(std::string v)
{
return (std::find(variants.begin(), variants.end(), v) != variants.end());
}
std::string getIdentifier()
{
return identifier;
}
};
class OptionSet
{
private:
std::vector<boost::any> options; //boost::any can't be the right way to do this, or is it?
std::vector<std::string> argvVec;
template<typename T>
Option<T>& findOptionByIdentifier(std::string identifier)
{
for(auto& o : options)
if(o.getIdentifier() == identifier) //of course this doesn't compile, because 'o' will always be of type 'boost::any', but what should I do instead?
return o;
throw std::runtime_error("error: unable to find option by identifier \"" + identifier + "\"\n");
}
template<typename T>
Option<T>& findOptionByVariant(std::string variant)
{
for(auto& o : options)
if(o.hasVariant(variant)) //probably almost the same compile error like in 'findOptionByIdentifier'
return o;
throw std::runtime_error("error: unable to find option by variant \"" + variant + "\"\n");
}
public:
template<typename t>
void add(Option<T> opt)
{
options.push_back(opt); //is this the right way to add instances of classes with different template parameters to a vector?
}
void setArgvVec(std::vector<std::string> newArgvVec)
{
argvVec = newArgvVec;
}
void process()
{
for(size_t i=0; i<argvVec.size(); i++)
{
Option<T>& opt = findOptionByVariant(argvVec[i]); //of course this doesn't compile either, but what should I do instead?
if(opt.hasValue())
{
if(i == argvVec.size()-1)
throw std::runtime_error("error: no value given for option \"" + argvVec[i] + "\"\n");
opt.setValueFromString(argvVec[i]); //boost::bad_lexical_cast should be caught here, but that's not important right now
i++;
}
}
}
template<typename T>
T getOptionValue(std::string identifier)
{
Option<T>& opt = findOptionByIdentifier(identifier); //a bit like the call to 'findOptionByVariant' in 'process()'. also, this variable does not have to be a reference
if(!opt.hasValue())
throw std::runtime_error("error: option with identifier \"" + identifier + "\" has no value\n");
return opt.getValue();
}
};
int main()
{
OptionSet optionSet;
//it's not guaranteed that OptionSet::add will always receive a rvalue, I just do it here for shorter code/simplicity
optionSet.add(Option<void>("help", { "-?", "--help" })); //if it's a void-option, the 'Option' does not have a value, if the template parameter is anything else, it has one (like below)
optionSet.add(Option<std::string>("message", { "-m", "--message" }));
optionSet.add(Option<int>("number", { "-n", "--number" }));
optionSet.add(Option<double>("pi", { "-p", "--pi" }));
optionSet.setArgvVec({ "--help", "-m", "hello", "--number", "100", "--pi", "3.14" });
optionSet.process();
std::string message = optionSet.getOptionValue("message");
int number = optionSet.getOptionValue("number");
double pi = optionSet.getOptionValue("pi");
std::cout << "Message: " << message << "\n"; //should output 'hello'
std::cout << "Number: " << number << "\n"; //should output '100'
std::cout << "Pi: " << pi << "\n"; //should output something like '3.140000'
return 0;
}
I am not sure I fully understood the question, but I will try to answer it.
I want to store multiple instances of one class with different
template parameters
There is no such thing. A template with different template paramter is a different class. However, you seem to be solving it successfully through boost::any. You could also use another type-erasure technique - for example, have a non-template parent to all your options, or switch to non-type-erasure boost::variant, as it seems like you only have a limited number of possible option types.
By using using, std::enable_if_t and std::is_same I created a type
called OptionHasValue...
First of all, I would not use SFINAE in this example. Simple partial specialization will suffice. As for opt.setValueFromString(argvVec[i]); just create a NOOP function in void option class.
As for the last question, just use a templated function which receives a reference to the return type, instead of returning it.

Uses of pointers non-type template parameters?

Has anyone ever used pointers/references/pointer-to-member (non-type) template parameters?
I'm not aware of any (sane/real-world) scenario in which that C++ feature should be used as a best-practice.
Demonstation of the feature (for pointers):
template <int* Pointer> struct SomeStruct {};
int someGlobal = 5;
SomeStruct<&someGlobal> someStruct; // legal c++ code, what's the use?
Any enlightenment will be much appreciated!
Pointer-to-function:
Pointer-to-member-function and pointer-to-function non-type parameters are really useful for some delegates. It allows you to make really fast delegates.
Ex:
#include <iostream>
struct CallIntDelegate
{
virtual void operator()(int i) const = 0;
};
template<typename O, void (O::*func)(int)>
struct IntCaller : public CallIntDelegate
{
IntCaller(O* obj) : object(obj) {}
void operator()(int i) const
{
// This line can easily optimized by the compiler
// in object->func(i) (= normal function call, not pointer-to-member call)
// Pointer-to-member calls are slower than regular function calls
(object->*func)(i);
}
private:
O* object;
};
void set(const CallIntDelegate& setValue)
{
setValue(42);
}
class test
{
public:
void printAnswer(int i)
{
std::cout << "The answer is " << 2 * i << "\n";
}
};
int main()
{
test obj;
set(IntCaller<test,&test::printAnswer>(&obj));
}
Live example here.
Pointer-to-data:
You can use such non-type parameters to extend the visibility of a variable.
For example, if you were coding a reflexion library (which might very useful for scripting), using a macro to let the user declare his classes for the library, you might want to store all data in a complex structure (which may change over time), and want some handle to use it.
Example:
#include <iostream>
#include <memory>
struct complex_struct
{
void (*doSmth)();
};
struct complex_struct_handle
{
// functions
virtual void doSmth() = 0;
};
template<complex_struct* S>
struct csh_imp : public complex_struct_handle
{
// implement function using S
void doSmth()
{
// Optimization: simple pointer-to-member call,
// instead of:
// retrieve pointer-to-member, then call it.
// And I think it can even be more optimized by the compiler.
S->doSmth();
}
};
class test
{
public:
/* This function is generated by some macros
The static variable is not made at class scope
because the initialization of static class variables
have to be done at namespace scope.
IE:
class blah
{
SOME_MACRO(params)
};
instead of:
class blah
{
SOME_MACRO1(params)
};
SOME_MACRO2(blah,other_params);
The pointer-to-data template parameter allows the variable
to be used outside of the function.
*/
std::auto_ptr<complex_struct_handle> getHandle() const
{
static complex_struct myStruct = { &test::print };
return std::auto_ptr<complex_struct_handle>(new csh_imp<&myStruct>());
}
static void print()
{
std::cout << "print 42!\n";
}
};
int main()
{
test obj;
obj.getHandle()->doSmth();
}
Sorry for the auto_ptr, shared_ptr is available neither on Codepad nor Ideone.
Live example.
The case for a pointer to member is substantially different from pointers to data or references.
Pointer to members as template parameters can be useful if you want to specify a member function to call (or a data member to access) but you don't want to put the objects in a specific hierarchy (otherwise a virtual method is normally enough).
For example:
#include <stdio.h>
struct Button
{
virtual ~Button() {}
virtual void click() = 0;
};
template<class Receiver, void (Receiver::*action)()>
struct GuiButton : Button
{
Receiver *receiver;
GuiButton(Receiver *receiver) : receiver(receiver) { }
void click() { (receiver->*action)(); }
};
// Note that Foo knows nothing about the gui library
struct Foo
{
void Action1() { puts("Action 1\n"); }
};
int main()
{
Foo foo;
Button *btn = new GuiButton<Foo, &Foo::Action1>(&foo);
btn->click();
return 0;
}
Pointers or references to global objects can be useful if you don't want to pay an extra runtime price for the access because the template instantiation will access the specified object using a constant (load-time resolved) address and not an indirect access like it would happen using a regular pointer or reference.
The price to pay is however a new template instantiation for each object and indeed it's hard to think to a real world case in which this could be useful.
The Performance TR has a few example where non-type templates are used to abstract how the hardware is accessed (the hardware stuff starts at page 90; uses of pointers as template arguments are, e.g., on page 113). For example, memory mapped I/O registered would use a fixed pointer to the hardware area. Although I haven't ever used it myself (I only showed Jan Kristofferson how to do it) I'm pretty sure that it is used for development of some embedded devices.
It is common to use pointer template arguments to leverage SFINAE. This is especially useful if you have two similar overloads which you couldn't use std::enable_if default arguments for, as they would cause a redefinition error.
This code would cause a redefinition error:
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
void foo (T x)
{
cout << "integral";
}
template <typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
void foo (T x)
{
cout << "floating";
}
But this code, which utilises the fact that valid std::enable_if_t constructs collapse to void by default, is fine:
// This will become void* = nullptr
template <typename T, std::enable_if_t<std::is_integral<T>::value>* = nullptr>
void foo (T x)
{
cout << "integral";
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value>* = nullptr>
void foo (T x)
{
cout << "floating";
}
Occasionally you need to supply a callback function having a particular signature as a function pointer (e.g. void (*)(int)), but the function you want to supply takes different (though compatible) parameters (e.g. double my_callback(double x)), so you can't pass its address directly. In addition, you might want to do some work before and after calling the function.
It's easy enough to write a class template that tucks away the function pointer and then calls it from inside its operator()() or some other member function, but this doesn't provide a way to extract a regular function pointer, since the entity being called still requires the this pointer to find the callback function.
You can solve this problem in an elegant and typesafe way by building an adaptor that, given an input function, produces a customised static member function (which, like a regular function and unlike a non-static member function, can have its address taken and used for a function pointer). A function-pointer template parameter is needed to embed knowledge of the callback function into the static member function. The technique is demonstrated here.