Something like "if constexpr" but for class definition - c++

if constexpr is a big step for getting rid of preprocessor in C++ programs. However it works only in functions - like in this example:
enum class OS
{
Linux,
MacOs,
MsWindows,
Unknown
};
#if defined(__APPLE__)
constexpr OS os = OS::MacOs;
#elif defined(__MINGW32__)
constexpr OS os = OS::MsWindows;
#elif defined(__linux__)
constexpr OS os = OS::Linux;
#else
constexpr OS os = OS::Unknown;
#endif
void printSystem()
{
if constexpr (os == OS::Linux)
{
std::cout << "Linux";
}
else if constexpr (os == OS::MacOs)
{
std::cout << "MacOS";
}
else if constexpr (os == OS::MsWindows)
{
std::cout << "MS Windows";
}
else
{
std::cout << "Unknown-OS";
}
}
But dreams about getting rid of preprocessor are not quite satisfied - because the following examples do not compile:
1 Cannot use it in class definition to define some members of class differently:
class OsProperties
{
public:
static void printName()
{
std::cout << osName;
}
private:
if constexpr (os == OS::Linux)
{
const char* const osName = "Linux";
}
else if constexpr (os == OS::MacOs)
{
const char* const osName = "MacOS";
}
else if constexpr (os == OS::MsWindows)
{
const char* const osName = "MS Windows";
}
else
{
const char* const osName = "Unknown";
}
};
2 Nor it works for not class-scope (like global scope):
if constexpr (os == OS::Linux)
{
const char* const osName = "Linux";
}
else if constexpr (os == OS::MacOs)
{
const char* const osName = "MacOS";
}
else if constexpr (os == OS::MsWindows)
{
const char* const osName = "MS Windows";
}
else
{
const char* const osName = "Unknown";
}
I am (almost) sure this is per C++17 specification that if constexpr works only within function bodies - but my questions are:
Q1 How to achieve the similar effect like if-constexpr in functions - for class and global scope in C++1z/C++14? And I am not asking here for yet another explanation of template specialization... But something that has similar simplicity as if constexpr...
Q2 Are there any plan to extend C++ for the above mentioned scopes?

How to achieve the similar effect like if-constexpr in functions - for class and global scope in C++1z/C++14? And I am not asking here for yet another explanation of template specialization...
You basically just said, "I want template specialization, but without all that pesky template specialization."
if constexpr is the tool for making the behavior of functions change based on compile-time constructs. Template specialization is the tool that C++ provides for making definitions change based on compile-time constructs. It is the only tool C++ provides for this functionality.
Now for your simplistic case of initializing a variable, you can always create and call a lambda. C++17 offers constexpr support for lambdas, and a lambda would be able to use if constexpr to decide what value to return.
Are there any plan to extend C++ for the above mentioned scopes?
No. Here are all of the proposals, and none of the ones from the past couple of years delve into this domain.
And it's highly unlikely they ever will.

An index type:
template<std::size_t I>
using index = std::integral_constant<std::size_t, I>;
first_truth takes a set of compile-time bools and says what the index of the first one is at compile time. If you pass it N compile-time bools, it returns N if all are false:
constexpr index<0> first_truth() { return {}; }
template<class...Rest>
constexpr index<0> first_truth(std::true_type, Rest...) { return {}; }
template<class...Rest>
constexpr auto first_truth(std::false_type, Rest...rest) {
return index<first_truth( rest... )+1>{};
}
dispatch takes a set of compile-time bools and returns a lambda. This lambda returns via perfect forwarding the first element that matches the first true compile time bool:
template<class...Bools>
constexpr auto dispatch(Bools...bools) {
constexpr auto index = first_truth(bools...);
return [](auto&&...fs){
return std::get< decltype(index){} >(
std::forward_as_tuple( decltype(fs)(fs)... )
);
};
}
A compile time bool type:
template<bool b>
using bool_t = std::integral_constant<bool, b>;
template<bool b>
bool_t<b> bool_k{};
Now we solve your problem:
const char* const osName =
dispatch(
bool_k<os == OS::Linux>,
bool_k<os == OS::MacOs>,
bool_k<os == OS::MsWindows>
)(
"Linux",
"MacOS",
"MS Windows",
"Unknown"
);
which should approximate a compile-time switch. We could tie the bools more closely to the arguments with a bit more work.
Code not compiled, probably contains tpyos.

how to define different types based on some compile time constant w/o template specialization?
Here it is:
constexpr auto osPropsCreate()
{
if constexpr (os == OS::Linux) {
struct Props { const char* name; int props1; using handle = int; };
return Props{"linux", 3};
} else if constexpr (os == OS::MacOs) {
struct Props { const char* name; using handle = float; };
return Props{"mac"};
} else if constexpr (os == OS::MsWindows) {
struct Props { const char* name; using handle = int; };
return Props{"win"};
} else
return;
}
using OsProps = decltype(osPropsCreate());
constexpr OsProps osProps = osPropsCreate();
As you can see - I used the new construction if constexpr to produce from some "implementation" function the type that depends on compile time constant. It is not as easy to use as static if in D language - but it works - I can do it:
int linuxSpecific[osProps.props1];
int main() {
std::cout << osProps.name << std::endl;
OsProps::handle systemSpecificHandle;
}
Next thing - define different functions depending on compile time constant:
constexpr auto osGetNameCreate() {
if constexpr (os == OS::Linux) {
struct Definition {
static constexpr auto getName() {
return "linux";
}
};
return Definition::getName;
} else if constexpr (os == OS::MacOs) {
// we might use lambda as well
return [] { return "mac"; };
} else if constexpr (os == OS::MsWindows) {
struct Definition {
static constexpr auto getName() {
return "win";
}
};
return Definition::getName;
} else
return;
}
constexpr auto osGetName = osGetNameCreate();
int main() {
std::cout << osGetName() << std::endl;
}
Actually, they can be either function-like objects (functors) or static member functions from nested classes. This does not matter - one have full freedom to define different things for different compile time constants (OS type in this case). Notice, that for unknown system we just return void - it will cause compilation error for unknown system...
Answering to second question:
The first answer provide it with reasoning in comments (link). My interpretation is that C++ standard committee is not ready for that change. Maybe competing with D will/would be a good reason to raise this subject once again...

Related

Is it possible to get names of template arguments without using macro? [duplicate]

I'm writing some template classes for parseing some text data files, and as such it is likly the great majority of parse errors will be due to errors in the data file, which are for the most part not written by programmers, and so need a nice message about why the app failed to load e.g. something like:
Error parsing example.txt. Value ("notaninteger")of [MySectiom]Key is not a valid int
I can work out the file, section and key names from the arguments passed to the template function and member vars in the class, however I'm not sure how to get the name of the type the template function is trying to convert to.
My current code looks like, with specialisations for just plain strings and such:
template<typename T> T GetValue(const std::wstring &section, const std::wstring &key)
{
std::map<std::wstring, std::wstring>::iterator it = map[section].find(key);
if(it == map[section].end())
throw ItemDoesNotExist(file, section, key)
else
{
try{return boost::lexical_cast<T>(it->second);}
//needs to get the name from T somehow
catch(...)throw ParseError(file, section, key, it->second, TypeName(T));
}
}
Id rather not have to make specific overloads for every type that the data files might use, since there are loads of them...
Also I need a solution that does not incur any runtime overhead unless an exception occurs, i.e. a completely compile time solution is what I want since this code is called tons of times and load times are already getting somewhat long.
EDIT: Ok this is the solution I came up with:
I have a types.h containg the following
#pragma once
template<typename T> const wchar_t *GetTypeName();
#define DEFINE_TYPE_NAME(type, name) \
template<>const wchar_t *GetTypeName<type>(){return name;}
Then I can use the DEFINE_TYPE_NAME macro to in cpp files for each type I need to deal with (eg in the cpp file that defined the type to start with).
The linker is then able to find the appropirate template specialisation as long as it was defined somewhere, or throw a linker error otherwise so that I can add the type.
The solution is
typeid(T).name()
where typeid(T) returns std::type_info.
typeid(T).name() is implementation defined and doesn't guarantee human readable string.
Reading cppreference.com :
Returns an implementation defined null-terminated character string
containing the name of the type. No guarantees are given, in
particular, the returned string can be identical for several types and
change between invocations of the same program.
...
With compilers such as gcc and clang, the returned string can be piped through c++filt -t to be converted to human-readable form.
But in some cases gcc doesn't return right string. For example on my machine I have gcc whith -std=c++11 and inside template function typeid(T).name() returns "j" for "unsigned int". It's so called mangled name. To get real type name, use
abi::__cxa_demangle() function (gcc only):
#include <string>
#include <cstdlib>
#include <cxxabi.h>
template<typename T>
std::string type_name()
{
int status;
std::string tname = typeid(T).name();
char *demangled_name = abi::__cxa_demangle(tname.c_str(), NULL, NULL, &status);
if(status == 0) {
tname = demangled_name;
std::free(demangled_name);
}
return tname;
}
Jesse Beder's solution is likely the best, but if you don't like the names typeid gives you (I think gcc gives you mangled names for instance), you can do something like:
template<typename T>
struct TypeParseTraits;
#define REGISTER_PARSE_TYPE(X) template <> struct TypeParseTraits<X> \
{ static const char* name; } ; const char* TypeParseTraits<X>::name = #X
REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...
And then use it like
throw ParseError(TypeParseTraits<T>::name);
EDIT:
You could also combine the two, change name to be a function that by default calls typeid(T).name() and then only specialize for those cases where that's not acceptable.
As mentioned by Bunkar typeid(T).name is implementation defined.
To avoid this issue you can use Boost.TypeIndex library.
For example:
boost::typeindex::type_id<T>().pretty_name() // human readable
This trick was mentioned under a few other questions, but not here yet.
All major compilers support __PRETTY_FUNC__ (GCC & Clang) /__FUNCSIG__ (MSVC) as an extension.
When used in a template like this:
template <typename T> const char *foo()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
It produces strings in a compiler-dependent format, that contain, among other things, the name of T.
E.g. foo<float>() returns:
"const char* foo() [with T = float]" on GCC
"const char *foo() [T = float]" on Clang
"const char *__cdecl foo<float>(void)" on MSVC
You can easily parse the type names out of those strings. You just need to figure out how many 'junk' characters your compiler inserts before and after the type.
You can even do that completely at compile-time.
The resulting names can slightly vary between different compilers. E.g. GCC omits default template arguments, and MSVC prefixes classes with the word class.
Here's an implementation that I've been using. Everything is done at compile-time.
Example usage:
std::cout << TypeName<float>() << '\n';
std::cout << TypeName<decltype(1.2f)>(); << '\n';
Implementation: (uses C++20, but can be backported; see the edit history for a C++17 version)
#include <algorithm>
#include <array>
#include <cstddef>
#include <string_view>
namespace impl
{
template <typename T>
[[nodiscard]] constexpr std::string_view RawTypeName()
{
#ifndef _MSC_VER
return __PRETTY_FUNCTION__;
#else
return __FUNCSIG__;
#endif
}
struct TypeNameFormat
{
std::size_t junk_leading = 0;
std::size_t junk_total = 0;
};
constexpr TypeNameFormat type_name_format = []{
TypeNameFormat ret;
std::string_view sample = RawTypeName<int>();
ret.junk_leading = sample.find("int");
ret.junk_total = sample.size() - 3;
return ret;
}();
static_assert(type_name_format.junk_leading != std::size_t(-1), "Unable to determine the type name format on this compiler.");
template <typename T>
static constexpr auto type_name_storage = []{
std::array<char, RawTypeName<T>().size() - type_name_format.junk_total + 1> ret{};
std::copy_n(RawTypeName<T>().data() + type_name_format.junk_leading, ret.size() - 1, ret.data());
return ret;
}();
}
template <typename T>
[[nodiscard]] constexpr std::string_view TypeName()
{
return {impl::type_name_storage<T>.data(), impl::type_name_storage<T>.size() - 1};
}
template <typename T>
[[nodiscard]] constexpr const char *TypeNameCstr()
{
return impl::type_name_storage<T>.data();
}
The answer of Logan Capaldo is correct but can be marginally simplified because it is unnecessary to specialize the class every time. One can write:
// in header
template<typename T>
struct TypeParseTraits
{ static const char* name; };
// in c-file
#define REGISTER_PARSE_TYPE(X) \
template <> const char* TypeParseTraits<X>::name = #X
REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...
This also allows you to put the REGISTER_PARSE_TYPE instructions in a C++ file...
As a rephrasing of Andrey's answer:
The Boost TypeIndex library can be used to print names of types.
Inside a template, this might read as follows
#include <boost/type_index.hpp>
#include <iostream>
template<typename T>
void printNameOfType() {
std::cout << "Type of T: "
<< boost::typeindex::type_id<T>().pretty_name()
<< std::endl;
}
If you'd like a pretty_name, Logan Capaldo's solution can't deal with complex data structure: REGISTER_PARSE_TYPE(map<int,int>)
and typeid(map<int,int>).name() gives me a result of St3mapIiiSt4lessIiESaISt4pairIKiiEEE
There is another interesting answer using unordered_map or map comes from https://en.cppreference.com/w/cpp/types/type_index.
#include <iostream>
#include <unordered_map>
#include <map>
#include <typeindex>
using namespace std;
unordered_map<type_index,string> types_map_;
int main(){
types_map_[typeid(int)]="int";
types_map_[typeid(float)]="float";
types_map_[typeid(map<int,int>)]="map<int,int>";
map<int,int> mp;
cout<<types_map_[typeid(map<int,int>)]<<endl;
cout<<types_map_[typeid(mp)]<<endl;
return 0;
}
typeid(uint8_t).name() is nice, but it returns "unsigned char" while you may expect "uint8_t".
This piece of code will return you the appropriate type
#define DECLARE_SET_FORMAT_FOR(type) \
if ( typeid(type) == typeid(T) ) \
formatStr = #type;
template<typename T>
static std::string GetFormatName()
{
std::string formatStr;
DECLARE_SET_FORMAT_FOR( uint8_t )
DECLARE_SET_FORMAT_FOR( int8_t )
DECLARE_SET_FORMAT_FOR( uint16_t )
DECLARE_SET_FORMAT_FOR( int16_t )
DECLARE_SET_FORMAT_FOR( uint32_t )
DECLARE_SET_FORMAT_FOR( int32_t )
DECLARE_SET_FORMAT_FOR( float )
// .. to be exptended with other standard types you want to be displayed smartly
if ( formatStr.empty() )
{
assert( false );
formatStr = typeid(T).name();
}
return formatStr;
}
I just leave it there.
If someone will still need it, then you can use this:
template <class T>
bool isString(T* t) { return false; } // normal case returns false
template <>
bool isString(char* t) { return true; } // but for char* or String.c_str() returns true
.
.
.
This will only CHECK type not GET it and only for 1 type or 2.
There're many good answers here, but I'd guess the easiest is to use a library, isn't it?
You can use this tiny lib, it's pretty cross-platform (tested with recent GCC/Clang/MSVC/ICC), supports C++11 onwards, works at compile time (consteval since C++20) and in theory it's going to support every compiler since the C++20's <source_location> gains wider support. A few more notes are in the README :)
I found this trick to publish a service interface with type information
#include <iostream>
using namespace std;
const char* nameOfType(int& ){ return "int";}
const char* nameOfType(const char* &){ return "string";}
const char* nameOfType(float& ){ return "float";}
const char* nameOfType(double& ){ return "double";}
template <typename T>
const char* templateFunction(T t){
return nameOfType(t) ;
};
int main()
{
cout<<"Hello World this is an ";
cout << templateFunction<int>(1) << std::endl;
cout << templateFunction<const char*>("") << std::endl;
cout << templateFunction<double>(3.14) <<std::endl;
return 0;
}
Hope it can help somebody.
Complementing the awesome answer by #HolyBlackCat which does the job at compile time. I've managed to encapsulate the logic inside a struct so there's no need for a "impl" namespace, instead the 'impl' functions are guarded in a private manner.
template<typename T>
struct TypeInfo
{
private:
struct RawTypeNameFormat
{
std::size_t leading_junk = 0;
std::size_t trailing_junk = 0;
};
template<typename U>
static constexpr const auto& RawTypeName()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
// Returns `false` on failure.
static constexpr inline bool GetRawTypeNameFormat(RawTypeNameFormat *format)
{
const auto &str = RawTypeName<int>();
for (std::size_t i = 0;; i++)
{
if (str[i] == 'i' && str[i+1] == 'n' && str[i+2] == 't')
{
if (format)
{
format->leading_junk = i;
format->trailing_junk = sizeof(str)-i-3-1; // `3` is the length of "int", `1` is the space for the null terminator.
}
return true;
}
}
return false;
}
static constexpr inline RawTypeNameFormat format =
[]{
static_assert(GetRawTypeNameFormat(nullptr), "Unable to figure out how to generate type names on this compiler.");
RawTypeNameFormat format;
GetRawTypeNameFormat(&format);
return format;
}();
// Returns the type name in a `std::array<char, N>` (null-terminated).
[[nodiscard]]
static constexpr auto GetTypeName()
{
constexpr std::size_t len = sizeof(RawTypeName<T>()) - format.leading_junk - format.trailing_junk;
std::array<char, len> name{};
for (std::size_t i = 0; i < len - 1; i++)
name[i] = RawTypeName<T>()[i + format.leading_junk];
return name;
}
public:
[[nodiscard]]
static cstring Name()
{
static constexpr auto name = GetTypeName();
return name.data();
}
[[nodiscard]]
static cstring Name(const T&)
{
return name();
}
}
Example usage:
auto myTypeName = TypeInfo<MyType>::Name();
or:
const char* myTypeName = TypeInfo<MyType>::Name();
Since c++20 we can use std::source_location::function_name() to get a string containing the function name and arguments.
template<typename T>
consteval auto type_name()
{
std::string_view func_name(std::source_location::current().function_name()); // returns something like: consteval auto type_name() [with T = int]
auto extracted_params = ... Do some post processing here to extract the parameter names.
return extracted_params;
}
N.B.: at the time of writing (Oct 2022) MSVC does not report the template parameters, so this solution will not work there. Unfortunately, the form of the return value of function_name() isn't specified in the standard, but we may at least hope that they will add the template parameters in later versions.
Example

Multiple return type from function - C++

Is there any way (conventional or no) to get a choice between multiple specified return types from a function. For example:
/* Concept code... */
class var {
public:
union {
bool _bool;
int _int;
char* _char_pointer;
} primitive_value;
std::string type;
var(bool arg) { primitive_value._bool = arg; type = "bool"; }
var(int arg) { primitive_value._int = arg; type = "int"; }
var(char* arg) { primitive_value._char_pointer = arg; type = "char*"; }
// Function/ method that could return `bool`, `int` or `char*`
<bool, int, char*> valueOf() const {
if (type == "bool") return primitive_value._bool;
else if (type == "int") return primitive_value._int;
else if (type == "char*") return primitive_value._char_pointer;
}
};
There is a reference to a similar question here I've seen that suggested using void* pointers or union's but I have yet to fully understand how those work.
No container types (such as std::any, std::optional, std::variant) are allowed because I want to know if there is an alternative to those as well.
To add on, this is all in the name of curiosity. Currently I am searching the optional and variant header files to know how the feature I'm asking for was implemented but no luck so far.
I'm hoping the platform here could have a practical solution to this potential problem.
You can use a mix of template function and if constexpr (C++17):
template<typename T>
T valueOf() const {
if constexpr(std::is_same<T, bool>) return _boolValueOf();
else if constexpr(std::is_same<T, int>) return _intValueOf();
else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf();
}
Requires passing the type, but then the signature could be:
template<typename T>
T valueOf(const T& d) const {
if constexpr(std::is_same<T, bool>) return _boolValueOf(d);
else if constexpr(std::is_same<T, int>) return _intValueOf(d);
else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf(d);
}
High-level and recomended solution is std::any, std::variant, std::optional. Low-level, hackish dangerous, final solution is union, void*, static_cast...
If you want neither, there is no more left to try. Do you finally want to do it in C++?
If are interested in the implementation of those high-level facilities, you can check the source code on open source implementations. But you will eventually find that those implementations device the low level constructs pointed above.
First to have different return types you need to use a template to differentiate the functions. Then you can call var(true).valueOf<bool>() for example. You will have to specify the template on every call so the compiler knows what function (and return type) to use. This can't be deduced on it's own.
Secondly the var.type is a string that can only be checked at runtime. So var(42).valueOf<bool>() compiles just fine. You would have to check var.type against the template argument at runtime and throw an exception when the types don't match.
Not an ideal design.
For you valueOf function, imo, user-defined conversion is also a choice:
operator std::string()
{
return primitive_value._char_pointer;
}
operator bool()
{
return primitive_value._bool;
}
operator int()
{
return primitive_value._int;
}
......
Then you can use like this:
var v1("hello");
var v2(true);
var v3(10);
std::string a = v1;
bool b = v2;
int c = v3;
std::cerr << static_cast<std::string>(v1) << '\n';
std::cerr << std::boolalpha << static_cast<bool>(v2) << '\n';
std::cerr << static_cast<int>(v3) << '\n';
If you still hope to use function, just add a operator():
var
operator()()
{
return *this;
}
Then you can:
var v1("hello");
var v2(true);
var v3(10);
std::string a = v1();
bool b = v2();
int c = v3();
But still a little ugly, right? Just add your valueOf function:
var
valueOf()
{
return *this;
}
Then:
var v1("hello");
var v2(true);
var v3(10);
std::string a = v1.valueOf();
bool b = v2.valueOf();
int c = v3.valueOf();
But these solutions have many limitions. if constexpr provided by Matthieu Brucher is more powerful. Just all about provide a idea here : ).
But please note, unlike if constexpr, the ways I provided is not really multiple types return, just user-defined conversion.
Of course, there are more solutions, like sfinae(use enable_if and is_same in return type), or tag dispatch, but both of them require template

how to use traits to access compile-time const value?

I am working on a project where the behavior of a certain function need to switch between a few values:
class James{
public:
James(){
if(a==0){
//do this
}else{
// do that
}
}
};
currently, 'a' is read from a config file at runtime. However, in practice, 'a' can be determined at compile-time, rather than run time. I am thinking about have a trait class
struct TraitZero{
constexpr int a = 0;
};
struct TraitOne{
constexpr int a = 1;
};
and then turn James into a template class
template<typename Trait>
class James{
constexpr int a = Trait::a;
public:
James(){
if(a=0){
//do this
}else{
// do that
}
}
};
I don't know where I got it wrong, but this does not compile.
I am wondering if anyone here has ever countered problems like this. Can anyone share some insights?
As has already been mentioned by skypjack, only static data members can be constexpr, and you need to use == instead of = in the conditional.
That said, since you want to determine a at compile time, it may be beneficial to you to branch based on a at compile time, as well. To do this, you can use SFINAE or (as of C++17) constexpr if.
Assuming the following three traits...
struct TraitZero{
static constexpr int a = 0;
};
struct TraitOne{
static constexpr int a = 1;
};
template<size_t N>
struct TraitN {
static constexpr int a = N;
};
We can do this as...
SFINAE:
template<typename Trait>
class James {
// Unnecessary, we can access Trait::a directly.
//static constexpr int a = Trait::a;
public:
template<bool AZero = Trait::a == 0>
James(std::enable_if_t<AZero, unsigned> = 0) {
std::cout << "Trait::a is 0.\n";
}
template<bool AOne = Trait::a == 1>
James(std::enable_if_t<AOne, int> = 0) {
std::cout << "Trait::a is 1.\n";
}
template<bool ANeither = (Trait::a != 0) && (Trait::a != 1)>
James(std::enable_if_t<ANeither, long> = 0) {
std::cout << "Trait::a is neither 0 nor 1.\n";
}
};
What this does is conditionally select one of the versions of James() based on the value of Traits::a, using dummy parameters to enable overloading; this is simpler for functions other than constructors and destructors, as enable_if can be used on their return type.
Note the use of template parameters, instead of directly checking Trait::a in the enable_ifs themselves. As SFINAE can only be performed with types and expressions in the immediate context of the functions, these are used to "drag it in", so to speak; I like to perform the logic while doing so, as it minimises the intrusiveness of the enable_if.
constexpr if:
template<typename Trait>
class James {
// Unnecessary, we can access Trait::a directly.
//static constexpr int a = Trait::a;
public:
James() {
if constexpr (Trait::a == 0) {
std::cout << "Trait::a is 0.\n";
} else if constexpr (Trait::a == 1) {
std::cout << "Trait::a is 1.\n";
} else {
std::cout << "Trait::a is neither 0 nor 1.\n";
}
}
};
As can be seen here, constexpr if can be used to create cleaner, more natural code than SFINAE, with the advantage that it will still be evaluated at compile time instead of run time; unfortunately, it isn't yet supported by most compilers. [In this particular case, each version of James() will also be one machine instruction shorter (when compiled with GCC 7.0), due to not using a dummy parameter to differentiate between overloads.]
More specifically, with constexpr if, statement-false is discarded if the condition is true, and statement-true is discarded if it's false; in effect, this basically means that the compiler sees the entire constexpr if statement as the branch which would be executed. In this case, for example, the compiler will generate one of the following three functions, based on the value of Trait::a.
// If Trait::a == 0:
James() {
std::cout << "Trait::a is 0.\n";
}
// If Trait::a == 1:
James() {
std::cout << "Trait::a is 1.\n";
}
// If Trait::a == anything else:
James() {
std::cout << "Trait::a is neither 0 nor 1.\n";
}
In either case, with the following code...
int main() {
James<TraitZero> j0;
James<TraitOne> j1;
James<TraitN<2>> j2;
}
The following output is generated:
Trait::a is 0.
Trait::a is 1.
Trait::a is neither 0 nor 1.
Each type's constructor will be coded specifically to output the appropriate line, and none of the three constructors will actually contain any branching.
Note that I only marked member a as unnecessary out of personal preference; since I can access Trait::a directly, I prefer to do so, so I won't have to check what a is if I ever forgoet. Feel free to use it if you want to, or if it's needed elsewhere.
a data members must be declared as constexpr and static to be used the way you are trying to use them:
struct TraitZero{
static constexpr int a = 0;
};
struct TraitOne{
static constexpr int a = 1;
};
Put aside the fact that it's be ill-formed as it stands, you wouldn't be allowed to access it as Traits::a otherwise.
The same applies to the class James:
template<typename Trait>
class James{
static constexpr int a = Trait::a;
//...
};
Note also that probably the following isn't what you want:
if(a=0){
Even if you were allowed to modify a (and you are not for it's a static constexpr data member), in this case you would have assigned 0 to a and constantly got the else branch.
Most likely you were looking for something similar but slightly different:
if(a == 0){
Below is an example based on your code once fixed:
#include<iostream>
struct TraitZero{
static constexpr int a = 0;
};
struct TraitOne{
static constexpr int a = 1;
};
template<typename Trait>
class James{
static constexpr int a = Trait::a;
public:
James(){
if(a==0){
std::cout << "0" << std::endl;
}else{
std::cout << "1" << std::endl;
}
}
};
int main() {
James<TraitZero> j0;
James<TraitOne> j1;
}
Why not pass a #define at compile time using the -D option?
For example: Including a #define in all .c source files at compile time

Count on enum C++ automatic

I've come to a pattern when writing enums in C++. It is like this:
class Player
{
public:
class State
{
public:
typedef enum
{
Stopped,
Playing,
Paused
}PossibleValues;
static const int Count() {return Paused+1;};
static const PossibleValues Default() {return Stopped;};
};
//...
}
This solves a some of the usual issues with enums, like pollution of outside namespaces, etc. But there is still a thing I don't like: The Count() is done manually. There are only two ways I know how to do it: this one is calculated from Last+1; or write plain hardcoded.
Question is: Is there some way, like using preprocessor macros, that automatically gets the count, to put it after in the Count() method? Attention: I don't want to have a last fake element called Count inside the enum, polluting it!
Thanks in advance!
UPDATE 1:
There is an interesting discussion on Implementation of N4428 enum reflection in standard C++11 (partial) for a proposal of more advanced enums.
UPDATE 2:
Interesting document N4451- Static reflection (rev. 3) on its sections 3.16, 3.17, A.7, A.8 about MetaEnums and MetaEnumClasses.
UPDATE 3:
I came to another interesting pattern using an enum class, after I've seen https://bytes.com/topic/c/answers/127908-numeric_limits-specialization#post444962. If the enum class's enumerator list is continuously integer, by defining its maximum and its minimum, we can check whether a value belongs to it or not.
If the purpose of using the Count() method on the Player::State was to check if a value was in the enum, that purpose has also been achieved with the numeric_limits approach, and is even superior, as it is not required the enumerator list begins with a ZERO valued item!
enum class Drink
{
Water,
Beer,
Wine,
Juice,
};
#pragma push_macro("min")
#undef min
#pragma push_macro("max")
#undef max
namespace std
{
template <> class numeric_limits < Drink >
{
public:
static const/*expr*/ bool is_specialized = true;
static const/*expr*/ Drink min() /*noexcept*/ { return Drink::Water; }
static const/*expr*/ Drink max() /*noexcept*/ { return Drink::Juice; }
static const/*expr*/ Drink lowest() /*noexcept*/ { return Drink::Water; }
static const/*expr*/ Drink default() /*noexcept*/ { return Drink::Beer; }
};
}
#pragma pop_macro("min")
#pragma pop_macro("max")
CASES OF USE:
A variable from the application:
Drink m_drink;
which in constructor is initialized with:
m_drink = numeric_limits<Drink>::default();
On the initialization of a form, I can do:
pComboDrink->SetCurSel(static_cast<int>(theApp.m_drink));
On it, for adapting the interface to changes done by the user, I can do a switch with scoped enum class values:
switch (static_cast<Drink>(pComboDrink->GetCurSel()))
{
case Drink::Water:
case Drink::Juice:
pAlcohoolDegreesControl->Hide();
break;
case Drink::Beer:
case Drink::Wine:
pAlcohoolDegreesControl->Show();
break;
default:
break;
}
And on the dialog's confirmation procedure (OnOK), I can check if the value is out of boundaries, before saving it to the respective app var:
int ix= pComboDrink->GetCurSel();
if (ix == -1)
return FALSE;
#pragma push_macro("min")
#undef min
#pragma push_macro("max")
#undef max
if (ix < static_cast<int> (std::numeric_limits<Drink>::min()) || ix > static_cast<int> (std::numeric_limits<Drink>::max()) )
return FALSE;
#pragma pop_macro("min")
#pragma pop_macro("max")
theApp.m_drink= static_cast<Drink>(ix);
NOTES:
The keywords constexpr (I commented /*expr*/, leaving it as const ) and noexcept are commented only because the compiler I am using (Visual C++ 2013) does not support them yet at the current version.
Maybe you do not need the logic to temporary undefine the min and max macros.
I know that the default() does not fit on a "numeric limits" scope; but it seemed an handy place to put it on; even it coincides with the default word that in some contexts is a keyword!
No there isn't, and if you need this, you probably shouldn't be using an enum in the first place.
In your particular case, what's a use case where you'd ever want to call Count?
AFAIK there's no automatic compiler-supported keyword to get the total amount of elements in enum. OTOH this usually doesn't make sense: you may have multiple values with the same value, as long as the values don't have to have consequent values (i.e. you may assign the values manually, rather than rely on automatic numbering).
One common practice is to declare the enum in the following way:
typedef enum
{
Stopped,
Playing,
Paused,
count
}PossibleValues;
This way, if count is always defined last - it will give you the count of the enum elements, assuming the numbering starts from 0 and is consequent.
Reposting an answer from a similar question (What is the best way for non sequencial integer c++ enums) because it was kind of relevant to an otherwise pretty much unanswered question.
A pattern you could use to get what you want is to use an std::initializer_list to store all the values of your enum.
namespace PossibleValues
{
enum Type
{
ZERO= 0,
PLUS180= 180,
PLUS90= 90,
MINUS90= -90
};
constexpr auto Values = {ZERO, PLUS180, PLUS90, MINUS90};
size_t Count() { return Values.size(); }
Type Default() { return *begin(Values); }
}
This also has the benefit of being able to iterate of the values of the enum even if they don't have linear values.
And I think you could possibly generate both the enum, the initializer list and the functions from a single macro with a variadic macro, though in the best of worlds this kind of thing should be in the standard.
Edit: When I used PossibleValues as an enum or used a struct for PossibleValues, my compiler would complain about incomplete type. Using a namespace for an enum is a bit unusual, but it works fine.
The solution from https://stackoverflow.com/a/60216003/12894563 can be improved. We can save enums expressions in a static vector and iterate, obtain min/max and etc
Usage:
#include <type_traits>
#include <algorithm>
#include <vector>
#include <iostream>
#define make_enum(Name, Type, ...) \
struct Name { \
enum : Type { \
__VA_ARGS__ \
}; \
static auto count() { return values.size(); } \
\
static inline const std::vector<Type> values = [] { \
static Type __VA_ARGS__; return std::vector<Type>({__VA_ARGS__}); \
}(); \
static Type min() \
{ \
static const Type result = *std::min_element(values.begin(), values.end()); \
return result; \
} \
static Type max() \
{ \
static const Type result = *std::max_element(values.begin(), values.end()); \
return result; \
} \
}
make_enum(FakeEnum, int, A = 1, B = 0, C = 2, D);
int main(int argc, char *argv[])
{
std::cout << FakeEnum::A << std::endl
<< FakeEnum::min() << std::endl
<< FakeEnum::max() << std::endl
<< FakeEnum::count() << std::endl;
return 0;
}
Must the type of PossibleValues be an enum? If you just need something that behaves like an enum, you can do the following:
#include <iostream>
#include <functional>
#include <set>
template <typename Representation, typename T>
class Iterable_Strong_Enum
{
private:
struct T_Ptr_Less : public std::binary_function<T const *, T const *, bool>
{
bool operator()(T const * x, T const * y) const
{
return x->get_representation() < y->get_representation();
}
};
public:
typedef std::set<T const *, T_Ptr_Less> instances_list;
typedef typename instances_list::const_iterator const_iterator;
Representation const & get_representation() const { return _value; }
static Representation const & min() { return (*_instances.begin())->_value; }
static Representation const & max() { return (*_instances.rbegin())->_value; }
static T const * corresponding_enum(Representation const & value)
{
const_iterator it = std::find_if(_instances.begin(), _instances.end(), [&](T const * e) -> bool
{
return e->get_representation() == value;
});
if (it != _instances.end())
{
return *it;
}
else
{
return nullptr;
}
}
bool operator==(T const & other) const { return _value == other._value; }
bool operator!=(T const & other) const { return _value != other._value; }
bool operator< (T const & other) const { return _value < other._value; }
bool operator<=(T const & other) const { return _value <= other._value; }
bool operator> (T const & other) const { return _value > other._value; }
bool operator>=(T const & other) const { return _value >= other._value; }
static bool is_valid_value(Representation const & value) { return corresponding_enum(value) != nullptr; }
static typename instances_list::size_type size() { return _instances.size(); }
static const_iterator begin() { return _instances.begin(); }
static const_iterator end() { return _instances.end(); }
protected:
explicit Iterable_Strong_Enum(Representation const & value);
private:
Representation _value;
static instances_list _instances;
};
template <typename Representation, typename T>
Iterable_Strong_Enum<Representation, T>::Iterable_Strong_Enum(Representation const & value)
: _value(value)
{
_instances.insert(static_cast<T const *>(this));
}
class PossibleValues : public Iterable_Strong_Enum<int, PossibleValues>
{
public:
static const PossibleValues Stopped;
static const PossibleValues Playing;
static const PossibleValues Pause;
protected:
private:
explicit PossibleValues(int value);
};
PossibleValues::PossibleValues(int value) : Iterable_Strong_Enum<int, PossibleValues>(value) { }
// you need to call that explicitly
Iterable_Strong_Enum<int, PossibleValues>::instances_list Iterable_Strong_Enum<int, PossibleValues>::_instances;
const PossibleValues PossibleValues::Stopped(0);
const PossibleValues PossibleValues::Playing(1);
const PossibleValues PossibleValues::Pause(2);
void stackoverflow()
{
std::cout << "There are " << PossibleValues::size() << " different possible values with representation: " << std::endl;
for (auto pv = PossibleValues::begin(); pv != PossibleValues::end(); ++pv)
{
PossibleValues possible_value = **pv;
std::cout << possible_value.get_representation() << std::endl;
}
}
I'm kinda torn about that solution. On the one hand, its pretty general and on the other hand its a big hammer for a small problem.

C++ Get name of type in template

I'm writing some template classes for parseing some text data files, and as such it is likly the great majority of parse errors will be due to errors in the data file, which are for the most part not written by programmers, and so need a nice message about why the app failed to load e.g. something like:
Error parsing example.txt. Value ("notaninteger")of [MySectiom]Key is not a valid int
I can work out the file, section and key names from the arguments passed to the template function and member vars in the class, however I'm not sure how to get the name of the type the template function is trying to convert to.
My current code looks like, with specialisations for just plain strings and such:
template<typename T> T GetValue(const std::wstring &section, const std::wstring &key)
{
std::map<std::wstring, std::wstring>::iterator it = map[section].find(key);
if(it == map[section].end())
throw ItemDoesNotExist(file, section, key)
else
{
try{return boost::lexical_cast<T>(it->second);}
//needs to get the name from T somehow
catch(...)throw ParseError(file, section, key, it->second, TypeName(T));
}
}
Id rather not have to make specific overloads for every type that the data files might use, since there are loads of them...
Also I need a solution that does not incur any runtime overhead unless an exception occurs, i.e. a completely compile time solution is what I want since this code is called tons of times and load times are already getting somewhat long.
EDIT: Ok this is the solution I came up with:
I have a types.h containg the following
#pragma once
template<typename T> const wchar_t *GetTypeName();
#define DEFINE_TYPE_NAME(type, name) \
template<>const wchar_t *GetTypeName<type>(){return name;}
Then I can use the DEFINE_TYPE_NAME macro to in cpp files for each type I need to deal with (eg in the cpp file that defined the type to start with).
The linker is then able to find the appropirate template specialisation as long as it was defined somewhere, or throw a linker error otherwise so that I can add the type.
The solution is
typeid(T).name()
where typeid(T) returns std::type_info.
typeid(T).name() is implementation defined and doesn't guarantee human readable string.
Reading cppreference.com :
Returns an implementation defined null-terminated character string
containing the name of the type. No guarantees are given, in
particular, the returned string can be identical for several types and
change between invocations of the same program.
...
With compilers such as gcc and clang, the returned string can be piped through c++filt -t to be converted to human-readable form.
But in some cases gcc doesn't return right string. For example on my machine I have gcc whith -std=c++11 and inside template function typeid(T).name() returns "j" for "unsigned int". It's so called mangled name. To get real type name, use
abi::__cxa_demangle() function (gcc only):
#include <string>
#include <cstdlib>
#include <cxxabi.h>
template<typename T>
std::string type_name()
{
int status;
std::string tname = typeid(T).name();
char *demangled_name = abi::__cxa_demangle(tname.c_str(), NULL, NULL, &status);
if(status == 0) {
tname = demangled_name;
std::free(demangled_name);
}
return tname;
}
Jesse Beder's solution is likely the best, but if you don't like the names typeid gives you (I think gcc gives you mangled names for instance), you can do something like:
template<typename T>
struct TypeParseTraits;
#define REGISTER_PARSE_TYPE(X) template <> struct TypeParseTraits<X> \
{ static const char* name; } ; const char* TypeParseTraits<X>::name = #X
REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...
And then use it like
throw ParseError(TypeParseTraits<T>::name);
EDIT:
You could also combine the two, change name to be a function that by default calls typeid(T).name() and then only specialize for those cases where that's not acceptable.
As mentioned by Bunkar typeid(T).name is implementation defined.
To avoid this issue you can use Boost.TypeIndex library.
For example:
boost::typeindex::type_id<T>().pretty_name() // human readable
This trick was mentioned under a few other questions, but not here yet.
All major compilers support __PRETTY_FUNC__ (GCC & Clang) /__FUNCSIG__ (MSVC) as an extension.
When used in a template like this:
template <typename T> const char *foo()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
It produces strings in a compiler-dependent format, that contain, among other things, the name of T.
E.g. foo<float>() returns:
"const char* foo() [with T = float]" on GCC
"const char *foo() [T = float]" on Clang
"const char *__cdecl foo<float>(void)" on MSVC
You can easily parse the type names out of those strings. You just need to figure out how many 'junk' characters your compiler inserts before and after the type.
You can even do that completely at compile-time.
The resulting names can slightly vary between different compilers. E.g. GCC omits default template arguments, and MSVC prefixes classes with the word class.
Here's an implementation that I've been using. Everything is done at compile-time.
Example usage:
std::cout << TypeName<float>() << '\n';
std::cout << TypeName<decltype(1.2f)>(); << '\n';
Implementation: (uses C++20, but can be backported; see the edit history for a C++17 version)
#include <algorithm>
#include <array>
#include <cstddef>
#include <string_view>
namespace impl
{
template <typename T>
[[nodiscard]] constexpr std::string_view RawTypeName()
{
#ifndef _MSC_VER
return __PRETTY_FUNCTION__;
#else
return __FUNCSIG__;
#endif
}
struct TypeNameFormat
{
std::size_t junk_leading = 0;
std::size_t junk_total = 0;
};
constexpr TypeNameFormat type_name_format = []{
TypeNameFormat ret;
std::string_view sample = RawTypeName<int>();
ret.junk_leading = sample.find("int");
ret.junk_total = sample.size() - 3;
return ret;
}();
static_assert(type_name_format.junk_leading != std::size_t(-1), "Unable to determine the type name format on this compiler.");
template <typename T>
static constexpr auto type_name_storage = []{
std::array<char, RawTypeName<T>().size() - type_name_format.junk_total + 1> ret{};
std::copy_n(RawTypeName<T>().data() + type_name_format.junk_leading, ret.size() - 1, ret.data());
return ret;
}();
}
template <typename T>
[[nodiscard]] constexpr std::string_view TypeName()
{
return {impl::type_name_storage<T>.data(), impl::type_name_storage<T>.size() - 1};
}
template <typename T>
[[nodiscard]] constexpr const char *TypeNameCstr()
{
return impl::type_name_storage<T>.data();
}
The answer of Logan Capaldo is correct but can be marginally simplified because it is unnecessary to specialize the class every time. One can write:
// in header
template<typename T>
struct TypeParseTraits
{ static const char* name; };
// in c-file
#define REGISTER_PARSE_TYPE(X) \
template <> const char* TypeParseTraits<X>::name = #X
REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...
This also allows you to put the REGISTER_PARSE_TYPE instructions in a C++ file...
As a rephrasing of Andrey's answer:
The Boost TypeIndex library can be used to print names of types.
Inside a template, this might read as follows
#include <boost/type_index.hpp>
#include <iostream>
template<typename T>
void printNameOfType() {
std::cout << "Type of T: "
<< boost::typeindex::type_id<T>().pretty_name()
<< std::endl;
}
If you'd like a pretty_name, Logan Capaldo's solution can't deal with complex data structure: REGISTER_PARSE_TYPE(map<int,int>)
and typeid(map<int,int>).name() gives me a result of St3mapIiiSt4lessIiESaISt4pairIKiiEEE
There is another interesting answer using unordered_map or map comes from https://en.cppreference.com/w/cpp/types/type_index.
#include <iostream>
#include <unordered_map>
#include <map>
#include <typeindex>
using namespace std;
unordered_map<type_index,string> types_map_;
int main(){
types_map_[typeid(int)]="int";
types_map_[typeid(float)]="float";
types_map_[typeid(map<int,int>)]="map<int,int>";
map<int,int> mp;
cout<<types_map_[typeid(map<int,int>)]<<endl;
cout<<types_map_[typeid(mp)]<<endl;
return 0;
}
typeid(uint8_t).name() is nice, but it returns "unsigned char" while you may expect "uint8_t".
This piece of code will return you the appropriate type
#define DECLARE_SET_FORMAT_FOR(type) \
if ( typeid(type) == typeid(T) ) \
formatStr = #type;
template<typename T>
static std::string GetFormatName()
{
std::string formatStr;
DECLARE_SET_FORMAT_FOR( uint8_t )
DECLARE_SET_FORMAT_FOR( int8_t )
DECLARE_SET_FORMAT_FOR( uint16_t )
DECLARE_SET_FORMAT_FOR( int16_t )
DECLARE_SET_FORMAT_FOR( uint32_t )
DECLARE_SET_FORMAT_FOR( int32_t )
DECLARE_SET_FORMAT_FOR( float )
// .. to be exptended with other standard types you want to be displayed smartly
if ( formatStr.empty() )
{
assert( false );
formatStr = typeid(T).name();
}
return formatStr;
}
I just leave it there.
If someone will still need it, then you can use this:
template <class T>
bool isString(T* t) { return false; } // normal case returns false
template <>
bool isString(char* t) { return true; } // but for char* or String.c_str() returns true
.
.
.
This will only CHECK type not GET it and only for 1 type or 2.
There're many good answers here, but I'd guess the easiest is to use a library, isn't it?
You can use this tiny lib, it's pretty cross-platform (tested with recent GCC/Clang/MSVC/ICC), supports C++11 onwards, works at compile time (consteval since C++20) and in theory it's going to support every compiler since the C++20's <source_location> gains wider support. A few more notes are in the README :)
I found this trick to publish a service interface with type information
#include <iostream>
using namespace std;
const char* nameOfType(int& ){ return "int";}
const char* nameOfType(const char* &){ return "string";}
const char* nameOfType(float& ){ return "float";}
const char* nameOfType(double& ){ return "double";}
template <typename T>
const char* templateFunction(T t){
return nameOfType(t) ;
};
int main()
{
cout<<"Hello World this is an ";
cout << templateFunction<int>(1) << std::endl;
cout << templateFunction<const char*>("") << std::endl;
cout << templateFunction<double>(3.14) <<std::endl;
return 0;
}
Hope it can help somebody.
Complementing the awesome answer by #HolyBlackCat which does the job at compile time. I've managed to encapsulate the logic inside a struct so there's no need for a "impl" namespace, instead the 'impl' functions are guarded in a private manner.
template<typename T>
struct TypeInfo
{
private:
struct RawTypeNameFormat
{
std::size_t leading_junk = 0;
std::size_t trailing_junk = 0;
};
template<typename U>
static constexpr const auto& RawTypeName()
{
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
// Returns `false` on failure.
static constexpr inline bool GetRawTypeNameFormat(RawTypeNameFormat *format)
{
const auto &str = RawTypeName<int>();
for (std::size_t i = 0;; i++)
{
if (str[i] == 'i' && str[i+1] == 'n' && str[i+2] == 't')
{
if (format)
{
format->leading_junk = i;
format->trailing_junk = sizeof(str)-i-3-1; // `3` is the length of "int", `1` is the space for the null terminator.
}
return true;
}
}
return false;
}
static constexpr inline RawTypeNameFormat format =
[]{
static_assert(GetRawTypeNameFormat(nullptr), "Unable to figure out how to generate type names on this compiler.");
RawTypeNameFormat format;
GetRawTypeNameFormat(&format);
return format;
}();
// Returns the type name in a `std::array<char, N>` (null-terminated).
[[nodiscard]]
static constexpr auto GetTypeName()
{
constexpr std::size_t len = sizeof(RawTypeName<T>()) - format.leading_junk - format.trailing_junk;
std::array<char, len> name{};
for (std::size_t i = 0; i < len - 1; i++)
name[i] = RawTypeName<T>()[i + format.leading_junk];
return name;
}
public:
[[nodiscard]]
static cstring Name()
{
static constexpr auto name = GetTypeName();
return name.data();
}
[[nodiscard]]
static cstring Name(const T&)
{
return name();
}
}
Example usage:
auto myTypeName = TypeInfo<MyType>::Name();
or:
const char* myTypeName = TypeInfo<MyType>::Name();
Since c++20 we can use std::source_location::function_name() to get a string containing the function name and arguments.
template<typename T>
consteval auto type_name()
{
std::string_view func_name(std::source_location::current().function_name()); // returns something like: consteval auto type_name() [with T = int]
auto extracted_params = ... Do some post processing here to extract the parameter names.
return extracted_params;
}
N.B.: at the time of writing (Oct 2022) MSVC does not report the template parameters, so this solution will not work there. Unfortunately, the form of the return value of function_name() isn't specified in the standard, but we may at least hope that they will add the template parameters in later versions.
Example