How to use different member variable names in a template? - c++

Edit: Completely rewrote the question to address suggestions in comments
In a large project that I participate in, there are a lot of classes that wrap messages, events, etc. They do not have a common ancestor and were (and still are) written by different people in different groups.
Most of these classes (or structs) have public members indicating error codes and descriptions. However, since they are used mostly within a single group and conventions are pretty loose, some of them name the members errStr, while others use errDesc.
For example:
struct X {
// stuff here...
int errCode;
std::string errStr;
};
struct Y {
// stuff here...
int errCode;
std::string errDesc;
};
I am trying to write a function template that will accept an object and print out the value of the whatever member variable that it has.
In pseudocode:
template<typename T>
bool logError(T const& x)
{
if (x.errCode == 0)
return true;
// if (T::errStr exists)
// log(x.errStr);
// else if (T::errDesc exists)
// log(x.errDesc);
return false;
}
What complicates matters is that the compiler that we use is VS2012, which is not fully C++11 compliant.
I have been messing with std::enable_if, std::is_same, etc for a while and so far the only result is an impressive collection of different compiler errors.
I was pointed to this by #T.C.
While it turned out to work quite well, it appears clunky and I was wondering if it can be simplified, or another solution offered, using the C++11 features that VS2012 supports.
Thank you!

In principle you can use SFINAE to detect the relevant member, but with C++03 (your compiler's standard) this yields complex, verbose code that's easy to break by maintenance – I give a complete example at the end below. The relevant techniques are covered in umpteen places on the web. E.g. I googled "c++ detect data member SFINAE" and hey presto, some GitHub code, and other examples. The ability to find information on the web, including basic googling, is very important to a developer. So, just try it.
An IMO more practical approach – because it's much simpler code that does not introduce maintenance problems and that goes in the direction you want the code to evolve – is to simply define overloads of an accessor function, one per class, like this:
string errorMessageOf( X const& o ) { return o.errStr; }
string errorMessageOf( Y const& o ) { return o.errDsc; }
Not everything needs to be a template.
Ordinary overloads are nice.
Your desired function template is then
template< class Type >
bool logError( Type const& x )
{
if (x.errCode == 0) return true; // A really dangerous thing to do
// Especially in Windows error code 0 a.k.a. NOERROR etc. is
// sometimes returned by GetLastError for a genuine failure. You
// should better treat it as "unknown cause".
clog << errorMessageOf( x ) << endl;
return not clog.fail(); // The return value is unspecified.
}
Example of instead using C++03 SFINAE, with code that works with Visual C++ 2012, and supporting an arbitrary number of names for the error message data member:
#include <iostream>
#include <stddef.h>
#include <string>
//----------------------------------------------- Machinery:
namespace reusable {
typedef ptrdiff_t Size;
template< Size n >
struct SizeCarrier_ { char nPlusOne[n + 1]; };
template< class Type, Type >
struct TypeFrom_;
} // namespace reusable
namespace my{
using std::string;
namespace impl {
using reusable::SizeCarrier_;
using reusable::TypeFrom_;
struct ErrorMsgMemberId { enum Enum{ noSuch, errStrName, errDescName }; };
template< class Type >
class ErrorMsgMemberId_
{
private:
template< class U >
static SizeCarrier_< ErrorMsgMemberId::errStrName >
memberId( TypeFrom_<string U::*, &U::errStr>* );
template< class U >
static SizeCarrier_<ErrorMsgMemberId::errDescName>
memberId( TypeFrom_<string U::*, &U::errDesc>* );
template< class U >
static SizeCarrier_<ErrorMsgMemberId::noSuch>
memberId( ... );
public:
static ErrorMsgMemberId::Enum const value = static_cast<ErrorMsgMemberId::Enum>(
sizeof( memberId< Type >( 0 ).nPlusOne ) - 1
);
};
template< ErrorMsgMemberId::Enum kind >
struct ErrorMsgFunc_;
template<>
struct ErrorMsgFunc_< ErrorMsgMemberId::errStrName >
{
template< class Type >
string operator()( Type const& o ) const
{ return o.errStr; }
};
template<>
struct ErrorMsgFunc_< ErrorMsgMemberId::errDescName >
{
template< class Type >
string operator()( Type const& o ) const
{ return o.errDesc; }
};
} // namespace impl
template< class Type >
string errorMsgOf( Type const& o )
{
static impl::ErrorMsgMemberId::Enum const member_id =
impl::ErrorMsgMemberId_< Type >::value;
return impl::ErrorMsgFunc_< member_id >()( o );
}
} // namespace my
//----------------------------------------------- Example usage:
struct X {
// stuff here...
int errCode;
std::string errStr;
};
struct Y {
// stuff here...
int errCode;
std::string errDesc;
};
struct Z {
// stuff here...
int errCode;
};
int main()
{
X const x = { 1, "X::errStr" };
Y const y = { 2, "Y::errDesc" };
Z const z = { 3 };
using namespace std;
cout << my::errorMsgOf( x ) << endl;
cout << my::errorMsgOf( y ) << endl;
//cout << my::errorMsgOf( z ) << endl; //! Fails with 'noSuch' in message.
}

Related

Usage of empty structs in C++

In some code that I was reading, I found the usage of empty struct like so:
struct input_iterator_tag { };
struct bidirectional_iterator_tag { };
struct random_access_iterator_tag { };
So in the rest of the code, it was used as what they call tag dispatching.
I was wondering if there is other usage of empty structs.
from an older post I saw that :
three major reasons we use empty structs in C++ are:
a base interface
a template parameter
a type to help overload resolution. (tag dispatching if I am not wrong)
Could someone explain that please?
a type to help overload resolution. (tag dispatching if I am not wrong)
When you want to use a complex template specialization pattern on some function, you don't try to go at it directly, but rather write:
template <typename T1, typename T2, other things maybe>
int foo(T1 param1, T2 param2 and so on)
{
using tag = put your complex stuff here, which produces an empty struct
detail::foo_impl(tag, std::forward<T1>(param1), std::forward<T2>(param2) and so on);
}
Now, the compiler doesn't have to decide between competing choices of template specialization, since with different tags you get incompatible functions.
a base interface
struct vehicle {
// common members and methods,
// including (pure) virtual ones, e.g.
virtual std::size_t num_maximum_occupants() = 0;
virtual ~vehicle() = default;
};
namespace mixins {
struct named { std::string name; };
struct wheeled { int num_wheels; public: rev() { }; };
} // namespace mixins
struct private_sedan : public vehicle, public wheeled, named {
// I dunno, put some car stuff here
//
// and also an override of `num_maximum_occupants()`
};
Making the base struct completely empty is perhaps not that common, but it's certainly possible if you use mixins a lot. And you could check for inheritance from vehicle (although I'm not sure I'd do that).
a template parameter
Not sure what this means, but venturing a guess:
template <typename T>
struct foo { };
template <typename T, typename N>
struct foo<std::array<T, N>> {
int value = 1;
};
If you now use foo<T>::value in a function, it will work only if T is int with few (?) exceptions.
I also tried to come up with examples:
as a base interface
// collection of very abstract vehicles
#include <vector>
struct Vehicle {};
struct Car : Vehicle {
int count_of_windows;
};
struct Bike : Vehicle {
int size_of_wheels;
};
std::vector<Vehicle> v{Bike{}, Car{}};
as a template parameter
// print same number in 3 different formats
#include <iostream>
struct dec {};
struct hex {};
struct octal {};
template<typename HOW = dec>
void print_me(int v);
template<>
void print_me<dec>(int v) {
auto f = std::cout.flags();
std::cout << std::dec << v << std::endl;
std::cout.flags(f);
}
template<>
void print_me<hex>(int v) {
auto f = std::cout.flags();
std::cout << std::hex << v << std::endl;
std::cout.flags( f );
}
template<>
void print_me<octal>(int v) {
auto f = std::cout.flags();
std::cout << std::oct << v << std::endl;
std::cout.flags(f);
}
int main() {
print_me(100);
print_me<hex>(100);
print_me<octal>(100);
}
a type to help overload resolution
// add a "noexcept" qualifier to overloaded function
// the noexcept version typically uses different functions
// and a custom "abort" handler
#include <iostream>
struct disable_exceptions {};
void is_number_1() {
int v;
std::cin >> v;
if (v != 1) {
throw new std::runtime_error("AAAA");
}
}
void is_number_1(disable_exceptions) noexcept {
int v;
// use C function - they don't throw
if (std::scanf("%d", &v) != 1) {
std::abort();
}
if (v != 1) {
std::abort();
}
}
int main() {
is_number_1();
is_number_1(disable_exceptions());
}
The example about "tag dispatching" can be found on cppreference iterator_tags. The iterator_category() member of an iterator is used to pick a different overload. That way you could write a different algorithm if for example iterator is forward_iterator, where you can only go forward, or it is a bidirectional_iterator, where your algorithm could change because you may walk back.

C++11 indexing template parameter packs at runtime in order to access Nth type

From this SO topic (and this blog post), I know how to access Nth type in a template parameter pack. For instance, one of the answers to the abovementioned SO question suggests this:
template<int N, typename... Ts> using NthTypeOf = typename std::tuple_element<N, std::tuple<Ts...>>::type;
using ThirdType = NthTypeOf<2, Ts...>;
However, these methods work only in compile-time. Trying to do something such as:
int argumentNumber = 2;
using ItsType = NthTypeOf<argumentNumber, Arguments...>;
would result in compile error:
Error : non-type template argument is not a constant expression
Is there a way to access Nth type at runtime?
Here's my use case:
My program reads a text file, which is basically an array of numbers. Each number i refers to the i-th type of a template parameter pack that my class is templated based on. Based on that type, I want to declare a variable of that type and do something differently with it. For example, if it's a string, I want to declare a string and do string matching, and if it's an integer, I would like to compute the square root of a number.
C++ is a statically​ typed language. As such the type of all variables needs to be known at compile time (and cannot vary). You want a type that depends on a runtime value. Luckily C++ also features dynamic typing of objects.
Warning: all code in this answer serves only for demonstration of the basic concept/idea. It's missing any kind of error handling, sane interfaces (constructors...), exception safety, ... . So don't use for production, consider using the implementations​ available from boost.
To use this feature you need what's called a polymorphic base class: a class with (at least) one virtual member function from which you derive further classes.
struct value_base {
// you want to be able to make copies
virtual std::unique_ptr<value_base> copy_me() const = 0;
virtual ~value_base () {}
};
template<typename Value_Type>
struct value_of : value_base {
Value_Type value;
std::unique_ptr<value_base> copy_me() const {
return new value_of {value};
}
};
You can then have a variable with static type of pointer or reference to that base class, which can point to/reference objects from both the base class as well as from any of those derived classes. If you have a clearly defined interface, then encode that as virtual member functions (think of Shape and area (), name (), ... functions) and make calls through that base class pointer/reference (as shown in the other answer). Otherwise use a (hidden) dynamic cast to obtain a pointer/reference with static type of the dynamic type:
struct any {
std:: unique_ptr<value_base> value_container;
// Add constructor
any(any const & a)
: value_container (a.value_container->copy_me ())
{}
// Move constructor
template<typename T>
T & get() {
value_of<T> * typed_container
= dynamic_cast<value_of<T> *>(value_container.get();)
if (typed_container == nullptr) {
// Stores another type, handle failure
}
return typed_container->value;
}
// T const & get() const;
// with same content as above
};
template<typename T, typename... Args>
any make_any (Args... && args) {
// Raw new, not good, add proper exception handling like make_unique (C++14?)
return {new T(std:: forward<Args>(args)...)};
}
Since object construction is done at runtime the actual type of the pointed to/referenced object may depend on runtime values:
template<typename T>
any read_and_construct (std:: istream & in) {
T value;
// Add error handling please
in >> value;
return make_any<T>(std:: move (value));
}
// ...
// missing: way of error handling
std::map<int, std:: function<any(std:: istream &)>> construction_map;
construction_map.insert(std::make_pair(1, read_and_construct<double>));
// and more
int integer_encoded_type;
// error handling please
cin >> integer_encoded_type;
// error handling please
any value = construction_map [integer_encoded_type] (cin);
As you may have noticed above code uses also a clearly defined interface for construction. If you don't intend to do lots of different things with the returned any objects, potentially storing them in various data structures over great parts of the time your program is running, then using an any type is most likely overkill and you should just put the type dependent code into those construction functions, too.
A serious drawback of such an any class is its generality: it's possible to store just about any type within it. This means that the (maximum) size of the (actually) stored object is not known during compilation, making use of storage with automatic duration (the "stack") impossible (in standard C++). This may lead to expensive usage of dynamic memory (the "heap"), which is considerably slower than automatic memory. This issue will surface whenever many copies of any objects have to be made, but is probably irrelevant (except for cache locality) if you just keep a collection of them around.
Thus, if you know at compile time the set of types which you must be able to store, then you can (at compile time) compute the maximum size needed, use a static array of that size and construct your objects inside that array (since C++11 you can achieve the same with a (recursive template) union, too):
constexpr size_t max_two (size_t a, size_t b) {
return (a > b) ? a : b;
}
template<size_t size, size_t... sizes>
constexpr size_t max_of() {
return max_two (size, max_of<sizes>());
}
template<typename... Types>
struct variant {
alignas(value_of<Types>...) char buffer[max_of<sizeof (value_of<Types>)...>()];
value_base * active;
// Construct an empty variant
variant () : active (nullptr)
{}
// Copy and move constructor still missing!
~variant() {
if (active) {
active->~value_base ();
}
}
template<typename T, typename... Args>
void emplace (Args... && args) {
if (active) {
active->~value_base ();
}
active = new (buffer) T(std:: forward<Args>(args)...);
}
};
C++ is a statically-typed language, which means that the types of variables cannot be decided or changed at runtime.
Because your array of numbers are input at runtime, it's impossible for you to use the NthTypeOf metafunction in the manner you describe, because NthTypeOf can only depend on a compile-time index.
In your use case, not only are the variables of different type, but the behavior is also different based on user input.
If you want different behavior based on a value determined at runtime, I suggest either a switch statement, a container of std::function, or a heterogeneous container of polymorphic "command" objects.
A solution based on a switch statement is pretty trivial, so I won't bother showing an example.
A std::function is a polymorphic wrapper around a function-like object. You can use a container of std::function to build a sort of dispatch table.
struct StringMatch
{
void operator()() const
{
std::string s1, s2;
std::cin >> s1 >> s2;
if (s1 == s2)
std::cout << "Strings match\n";
else
std::cout << "Strings don't match\n";
}
};
struct SquareRoot
{
void operator()() const
{
float x = 0;
std::cin >> x;
std::cout << "Square root is " << std::sqrt(x) <<"\n";
}
};
int main()
{
const std::map<int, std::function> commands =
{
{1, StringMatch()},
{2, SquareRoot()},
};
int commandId = 0;
std::cin >> commandId;
auto found = command.find(commandId);
if (found != commands.end())
(*found->second)();
else
std::cout << "Unknown command";
return 0;
}
The map can of course be replaced by a flat array or vector, but then you need to worry about "holes" in the command ID range.
If you need your command objects to be able to do more then execute themselves (like having properties, or support undo/redo), you can use a solution that uses polymorphism and is inspired by the traditional Command Pattern.
class Command
{
public:
virtual ~Command() {}
virtual void execute();
virtual std::string name() const;
virtual std::string description() const;
};
class StringMatch : public Command
{
public:
void execute() override
{
std::string s1, s2;
std::cin >> s1 >> s2;
if (s1 == s2)
std::cout << "Strings match\n";
else
std::cout << "Strings don't match\n";
}
std::string name() const override {return "StringMatch";}
std::string description() const override {return "Matches strings";}
};
class SquareRoot : public Command
{
public:
void execute() override
{
float x = 0;
std::cin >> x;
std::cout << "Square root is " << std::sqrt(x) <<"\n";
}
std::string name() const override {return "SquareRoot";}
std::string description() const override {return "Computes square root";}
};
int main()
{
constexpr int helpCommandId = 0;
const std::map<int, std::shared_ptr<Command>> commands =
{
{1, std::make_shared<StringMatch>()},
{2, std::make_shared<SquareRoot>()},
};
int commandId = 0;
std::cin >> commandId;
if (commandId == helpCommandId)
{
// Display command properties
for (const auto& kv : commands)
{
int id = kv.first;
const Command& cmd = *kv.second;
std::cout << id << ") " << cmd.name() << ": " << cmd.description()
<< "\n";
}
}
else
{
auto found = command.find(commandId);
if (found != commands.end())
found->second->execute();
else
std::cout << "Unknown command";
}
return 0;
}
Despite C++ being a statically-typed language, there are ways to emulate Javascript-style dynamic variables, such as the JSON for Modern C++ library or Boost.Variant.
Boost.Any can also be used for type erasure of your command arguments, and your command objects/functions would know how to downcast them back to their static types.
But such emulated dynamic variables will not address your need to have different behavior based on user/file input.
One possible approach when you want to do something with a run-time dependent type very locally, is to predict run-time values at the compile time.
using Tuple = std::tuple<int, double, char>;
int type;
std::cin >> type;
switch(type) {
case 0: {
using ItsType = std::tuple_element<0, Tuple>;
break;
}
case 1: {
using ItsType = std::tuple_element<1, Tuple>;
break;
}
default: std::cerr << "char is not handled yet." << std::endl;
break;
}
Only works with small type packs, of course.
Is there a way to access Nth type at runtime?
Yes, although per other answers, it may not be appropriate in this context.
Adapting this answer, you can iterate at compile time, and choose a type.
#include <iostream>
#include <fstream>
#include <string>
#include <type_traits>
#include <tuple>
#include <cmath>
std::ifstream in("my.txt");
void do_something(const std::string& x)
{
std::cout << "Match " << x << '\n';
}
void do_something(int x)
{
std::cout << "Sqrt of " << x << " = " << std::sqrt(x) << '\n';
}
template<std::size_t I, typename... Tp>
inline typename std::enable_if_t<I == sizeof...(Tp)> action_on_index_impl(size_t)
{ // reached end with I==number of types: do nothing
}
template<std::size_t I, typename... Tp>
inline typename std::enable_if_t<I < sizeof...(Tp)> action_on_index_impl(size_t i)
{
if (i == I){
// thanks to https://stackoverflow.com/a/29729001/834521 for following
std::tuple_element_t<I, std::tuple<Tp...>> x{};
in >> x;
do_something(x);
}
else
action_on_index_impl<I+1, Tp...>(i);
}
template<typename... Tp> void action_on_index(size_t i)
{
// start at the beginning with I=0
action_on_index_impl<0, Tp...>(i);
}
int main()
{
int i{};
while(in >> i, in)
action_on_index<std::string, int>(i);
return 0;
}
with my.txt
0 hello
1 9
0 world
1 4
output
Match hello
Sqrt of 9 = 3
Match world
Sqrt of 4 = 2
I needed to know how to access Nth type at runtime in a different context, hence my answer here (I wonder if there is a better way, particularly in C++14/17).

Better solution to data storage and passing

I'm trying to find a more elegant solution for some code I'm working on at the moment. I have data that needs to be stored then moved around, but I don't really want to take up any more space than I need to for the data that is stored.
I have 2 solutions, but neither seem very nice.
Using inheritance and a tag
enum class data_type{
first, second, third
};
class data_base{
public:
virtual data_type type() const noexcept = 0;
};
using data_ptr = data_base*;
class first_data: public data_base{
public:
data_type type() const noexcept{return data_type::first;}
// hold the first data type
};
// ...
Then you pass around a data_ptr and cast it to the appropriate type.
I really don't like this approach because it requires upwards casting and using bare pointers.
Using a union and storing all data types
enum class data_type{
first, second, third
};
class data{
public:
data(data_type type_): type(type_){}
data_type type;
union{
// first, second and third data types stored
};
};
But I don't like this approach because then you start wasting a lot of memory when you have a large data type that may get passed around.
This data will then be passed onto a function that will parse it into a greater expression. Something like this:
class expression{/* ... */};
class expr_type0: public expression{/* ... */};
// every expression type
using expr_ptr = expression*;
// remember to 'delete'
expr_ptr get_expression(){
data_ptr dat = get_data();
// interpret data
// may call 'get_data()' many times
expr_ptr expr = new /* expr_type[0-n] */
delete dat;
return expr;
}
and the problem arrises again, but it doesn't matter in this case because the expr_ptr doesn't need to be reinterpreted and will have a simple virtual function call.
What is a more elegant method of tagging and passing around the data to another function?
It's difficult to envisage exactly what you're looking for without more information. But if I wanted some framework that allowed me to store and retrieve data in some structured way, in as-yet-unknown storage devices this is the kind of way I'd be thinking.
This may not be the answer you're looking for, but I think there'll be concepts here that will inspire you in the right direction.
#include <iostream>
#include <tuple>
#include <boost/variant.hpp>
#include <map>
// define some concepts
// bigfoo is a class that's expensive to copy - so lets give it a shared-handle idiom
struct bigfoo {
struct impl {
impl(std::string data) : _data(std::move(data)) {}
void write(std::ostream& os) const {
os << "I am a big object. Don't copy me: " << _data;
}
private:
std::string _data;
};
bigfoo(std::string data) : _impl { std::make_shared<impl>(std::move(data)) } {};
friend std::ostream& operator<<(std::ostream&os, const bigfoo& bf) {
bf._impl->write(os);
return os;
}
private:
std::shared_ptr<impl> _impl;
};
// all the data types our framework handles
using abstract_data_type = boost::variant<int, std::string, double, bigfoo>;
// defines the general properties of a data table store concept
template<class...Columns>
struct table_definition
{
using row_type = std::tuple<Columns...>;
};
// the concept of being able to store some type of table data on some kind of storage medium
template<class IoDevice, class TableDefinition>
struct table_implementation
{
using io_device_type = IoDevice;
using row_writer_type = typename io_device_type::row_writer_type;
template<class...Args> table_implementation(Args&...args)
: _io_device(std::forward<Args>(args)...)
{}
template<class...Args>
void add_row(Args&&...args) {
auto row_instance = _io_device.open_row();
set_row_args(row_instance,
std::make_tuple(std::forward<Args>(args)...),
std::index_sequence_for<Args...>());
row_instance.commit();
}
private:
template<class Tuple, size_t...Is>
void set_row_args(row_writer_type& row_writer, const Tuple& args, std::index_sequence<Is...>)
{
using expand = int[];
expand x { 0, (row_writer.set_value(Is, std::get<Is>(args)), 0)... };
(void)x; // mark expand as unused;
}
private:
io_device_type _io_device;
};
// model the concepts into a concrete specialisation
// this is a 'data store' implementation which simply stores data to stdout in a structured way
struct std_out_io
{
struct row_writer_type
{
void set_value(size_t column, abstract_data_type value) {
// roll on c++17 with it's much-anticipated try_emplace...
auto ifind = _values.find(column);
if (ifind == end(_values)) {
ifind = _values.emplace(column, std::move(value)).first;
}
else {
ifind->second = std::move(value);
}
}
void commit()
{
std::cout << "{" << std::endl;
auto sep = "\t";
for (auto& item : _values) {
std::cout << sep << item.first << "=" << item.second;
sep = ",\n\t";
}
std::cout << "\n}";
}
private:
std::map<size_t, abstract_data_type> _values; // some value mapped by ascending column number
};
row_writer_type open_row() {
return row_writer_type();
}
};
// this is a model of a 'data table' concept
using my_table = table_definition<int, std::string, double, bigfoo>;
// here is a test
auto main() -> int
{
auto data_store = table_implementation<std_out_io, my_table>( /* std_out_io has default constructor */);
data_store.add_row(1, "hello", 6.6, bigfoo("lots and lots of data"));
return 0;
}
expected output:
{
0=1,
1=hello,
2=6.6,
3=I am a big object. Don't copy me: lots and lots of data
}

C++ - return different variable types

I don't know if this is possible but maybe there are other solutions to what I want. I am trying to get settings from a settings file. They can be strings (like names), integers or booleans. Of course, they are stored as text inside the file but I will create a class for opening and returning settings, yet not as string but as what each one of them are in fact.
class Settings {
public:
Settings(string FileName);
template <class T> T Setting(string SettingName);
}
The constructor would load the file, will parse the settings and store them as a map, for example.
Now, when I call the Setting member function I want it to identify what type is the value of the requested setting (if it is numeric, a integer, if is "true" or "false" a boolean, if is alphanumeric a string) and return a value of that type. An example
Settings UserPreferences("Preferences.cfg");
bool AutoLogin = UserPreferences.Setting("autologin"); // return bool
string UserName = UserPreferences.Setting("username"); // return string or char*
I had a look over templates but it looks like I have to specify what variable I expect when creating the Settings object but that's not the point. I am happy with declaring the type of the variable to return like this:
bool AutoLogin = UserPreferences.Setting<bool>("autologin");
string UserName = UserPreferences.Setting<string>("username");
but I don't know if that is possible. What do you think?
This is definitely possible, although you have to have some guarantee that it can cast to the given type. This is seen a lot in XNA's ContentLoader (albeit a much different system). You can use this approach to simplify and abstract how things are stored an retrieved. Consider:
class Loader
{
private:
vector<void*> _items;
public:
template <typename Type>
Type GetItem( int index ) { return (Type)(_items[ index ]); }
};
The idea is that as long as you can cast the internal data to the requested type reliably (more reliably than the example) than it is a perfectly legal operation. How to make that a guaranteed success is another question entirely, but you can definitely have methods whose return type is that of the their template types. Consider the following example (I used this is a college project for a resource loader):
Header.h
class BasicResource
{
public:
static const int ResourceID;
const int ID;
BasicResource( )
: ID( ResourceID )
{
}
};
class Loader
{
private:
vector<BasicResource*> _items;
public:
template <typename Type>
Type GetItem( int index );
};
#include "inline.inl"
Inline.inl
template <typename Type>
Type Loader::GetItem( int index )
{
auto item = _items[ index ];
if( item != nullptr && item->ID == Type::ResourceID )
{
return (Type)_item;
}
else
{
// Handle the fail case somehow
}
}
Inline files allow you to seperate your logic as you normally would, but include it in the header which allows for export of template methods.
Yes, it is certainly possible. I've written the following bit of complete code to prove the point:
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <stdexcept>
struct Settings
{
typedef std::map<std::string, std::string> SettingsMap;
template <class T> T as( const std::string& name ) const
{
std::istringstream is( getEntry( name ) );
T value;
if( is )
{
if( (is >> value) || (is.eof() && !is.fail()) )
{
return value;
}
}
//Exception handling not in scope of question
throw std::runtime_error( "..." );
};
const std::string& getEntry( const std::string& name ) const
{
SettingsMap::const_iterator pos( settingsMap_.find( name ) );
if( pos != settingsMap_.end() )
{
return pos->second;
}
//Not part of the scope of this answer....
throw std::invalid_argument( "No such setting..." );
}
Settings()
{
settingsMap_["mybool"] = "1";
settingsMap_["myint"] = "5";
settingsMap_["myfloat"] = "43.2";
}
SettingsMap settingsMap_;
};
int main()
{
Settings s;
std::cout << s.as<bool>("mybool") << " "
<< s.as<int>("myint") << " "
<< s.as<float>("myfloat");
return 0;
}
I've implemented something similar to this, but I've used boost::any as my mapped type, and I've read the actual type during the first parse, therefore ensuring that the stored type is correct. I've also used boost::lexical_cast instead of native istringstream, but I've omitted that for the purpose of proving the point.

C++ class member variable knowing its own offset

Is it possible to have a member variable, that would be able to calculate pointer to the containing object from pointer to itself (in it's method)?
Let's have a foreign call interface wrapped in API like this:
template <typename Class, MethodId Id, typename Signature>
class MethodProxy;
template <typename Class, MethodId Id, typename ReturnT, typename Arg1T>
class MethodProxy<Class, Id, ReturnT ()(Arg1T) {
public:
ReturnT operator()(Class &invocant, Arg1T arg1);
};
and similarly for other numbers of arguments from 0 to N. For each class on the foreign side, one C++ class is declared with some traits and this template uses those traits (and more traits for argument types) to find and invoke the foreign method. This can be used like:
Foo foo;
MethodProxy<Foo, barId, void ()(int)> bar;
bar(foo, 5);
Now what I would like to do is define Foo in such way, that I can call like:
Foo foo;
foo.bar(5);
without repeating the signature multiple times. (obviously creating a static member and wrapping the call in a method is simple, right). Well, in fact, that's still easy:
template <typename Class, MethodId Id, typename Signature>
class MethodMember;
template <typename Class, MethodId Id, typename ReturnT, typename Arg1T>
class MethodMember<Class, Id, ReturnT ()(Arg1T) {
MethodProxy<Class, Id, Signature> method;
Class &owner;
public:
MethodMember(Class &owner) : owner(owner) {}
ReturnT operator()(Arg1T arg1) { return method(owner, arg1); }
};
That however means the object will end up containing many copies of pointer to itself. So I am looking for a way to make these instances being able to calculate the owner pointer from this and some additional template arguments.
I was thinking along the lines of
template <typename Class, size_t Offset, ...>
class Member {
Class *owner() {
return reinterpret_cast<Class *>(
reinterpret_cast<char *>(this) - Offset);
}
...
};
class Foo {
Member<Foo, offsetof(Foo, member), ...> member;
...
};
but this complains that Foo is incomplete type at the point.
Yes, I know offsetof is supposed to only work for "POD" types, but in practice for any non-virtual member, which this will be, works. I have similarly tried to pass pointer-to-(that)-member (using dummy base-class) in that argument, but that does not work either.
Note, that if this worked, it could also be used to implement C#-like properties delegating to methods of the containing class.
I know how to do the wrapper methods mentioned above with boost.preprocessor, but the argument lists would have to be specified in a weird form. I know how to write macro to generate generic wrappers via templates, but that would probably give poor diagnostics. It would also be trivial if the calls could look like foo.bar()(5). But I'd like to know whether some clever trick would be possible (plus only such clever trick would probably be usable for properties too).
Note: The member type can't be actually specialized on either member pointer to it nor it's offset, because the type must be known before that offset can be assigned. That's because the type can affect required alignment (consider explicit/parcial specialization).
Asking a question is the best way to realize the answer, so this is where I've got:
The offset can't be a template argument, because the type has to be known before the offset can be calculated. So it has to be returned by a function of the argument. Let's add a tag type (dummy struct) and either a put an overloaded function into Owner or directly into the tag. That way we can define everything we need on one place (using a macro). The following code compiles fine with gcc 4.4.5 and prints correct pointer for all members:
#include <cstddef>
#include <iostream>
using namespace std;
(just preamble to make it really compile)
template <typename Owner, typename Tag>
struct offset_aware
{
Owner *owner()
{
return reinterpret_cast<Owner *>(
reinterpret_cast<char *>(this) - Tag::offset());
}
};
This is what's needed to make the object aware of it's own offset. Property or functor or some other code can be added freely to make it useful. Now we need to declare some extra stuff along with the member itself, so let's define this macro:
#define OFFSET_AWARE(Owner, name) \
struct name ## _tag { \
static ptrdiff_t offset() { \
return offsetof(Owner, name); \
} \
}; \
offset_aware<Owner, name ## _tag> name
This defines structure as the tag and puts in a function returning the required offset. Than it defines the data member itself.
Note, that the member needs to be public as defined here, but we could easily add a 'friend' declaration for the tag support protected and private properties. Now let's use it.
struct foo
{
int x;
OFFSET_AWARE(foo, a);
OFFSET_AWARE(foo, b);
OFFSET_AWARE(foo, c);
int y;
};
Simple, isn't it?
int main()
{
foo f;
cout << "foo f = " << &f << endl
<< "f.a: owner = " << f.a.owner() << endl
<< "f.b: owner = " << f.b.owner() << endl
<< "f.c: owner = " << f.c.owner() << endl;
return 0;
}
This prints the same pointer value on all lines. C++ standard does not allow members to have 0 size, but they will only have the size of their actual content or 1 byte if they are otherwise empty compared to 4 or 8 (depending on platform) bytes for a pointer.
1) There's a gcc extension which seemed fitting:
enum{ d_y = __builtin_choose_expr(N,offsetof(X,y),0) };
But it didn't work as expected, even though manual says
"the built-in function does not evaluate the expression that was not chosen"
2) member pointers seemed interesting, eg. offsetof can be defined like this:
template< class C, class T >
int f( T C::*q ) {
return (int)&((*(C*)0).*q);
}
But I still didn't find a way to turn this into constexpr.
3) For now, here's another version:
#include <stdio.h>
#pragma pack(1)
template <class A, int x>
struct B {
int z;
void f( void ) {
printf( "x=%i\n", x );
}
};
#define STRUCT( A ) template< int N=0 > struct A {
#define CHILD( A, N, B, y ) }; template<> struct A<N> : A<N-1> \
{ B<A<N>,sizeof(A<N-1>)> y;
#define STREND };
STRUCT( A )
int x0;
int x1;
CHILD( A,1, B, y );
short x2;
CHILD( A,2, B, z );
char x3;
STREND
typedef A<2> A1;
int main( void ) {
A1 a;
a.y.f();
a.z.f();
}
For now, here's one MS-specific solution, still thinking how to make it more general
#include <stdio.h>
#define offs(s,m) (size_t)&(((s *)0)->m)
#define Child(A,B,y) \
__if_exists(X::y) { enum{ d_##y=offs(X,y) }; } \
__if_not_exists(X::y) { enum{ d_##y=0 }; } \
B<A,d_##y> y;
template <class A, int x>
struct B {
int z;
void f( void ) {
printf( "x=%i\n", x );
}
};
template< class X >
struct A {
int x0;
int x1;
Child(A,B,y);
Child(A,B,z);
};
typedef A<int> A0;
typedef A<A0> A1;
int main( void ) {
A1 a;
a.y.f();
a.z.f();
}
Assuming the calls actually need a reference to the containing object, just store the reference to the owner. Unless you have specific memory profiling evidence that it's causing a significant memory increase to store the extra references, just do it the obvious way.