Why can't you pass literal strings in here? I made it work with a very slight workaround.
template<const char* ptr> struct lols {
lols() : i(ptr) {}
std::string i;
};
class file {
public:
static const char arg[];
};
decltype(file::arg) file::arg = __FILE__;
// Getting the right type declaration for this was irritating, so I C++0xed it.
int main() {
// lols<__FILE__> hi;
// Error: A template argument may not reference a non-external entity
lols<file::arg> hi; // Perfectly legal
std::cout << hi.i;
std::cin.ignore();
std::cin.get();
}
Because this would not be a useful utility. Since they are not of the allowed form of a template argument, it currently does not work.
Let's assume they work. Because they are not required to have the same address for the same value used, you will get different instantiations even though you have the same string literal value in your code.
lols<"A"> n;
// might fail because a different object address is passed as argument!
lols<"A"> n1 = n;
You could write a plugin for your text editor that replaces a string by a comma separated list of character literals and back. With variadic templates, you could "solve" that problem this way, in some way.
It is possible, but the the template argument must have external linkage, which precludes using literal strings and mitigates the utility of doing this.
An example I have is:
template<const char* name, const char* def_value=empty_>
struct env : public std::string
{
env()
{
const char* p = std::getenv(name);
assign(p ? p : def_value);
}
};
extern const char empty_[] = "";
std::string test = env<empty_>();
This is how I do it. Makes a lot more sense to me:
struct MyString { static const std::string val; };
const std::string MyString::val = "this is your string";
template<typename T>
void func()
{
std::cout << T::val << std::endl;
}
void main()
{
func<MyString>();
}
Good question, thought I'd throw my hat into the ring... I guess you can pass pointers to static variables as non-type template arguments. From C++20 it looks like it won't be an issue... Until then, here is some cheap macro to make it work.
template <const char *Name, typename T>
struct TaggedValue {
static constexpr char const *name{Name};
T value;
friend ostream &operator<<(ostream &o, const TaggedValue &a) {
return o << a.name << " = " << a.value;
}
};
#define ST(name, type)\
const char ST_name_##name[]{#name};\
using name = TaggedValue<ST_name_##name,type>;
ST(Foo, int);
ST(Bar, int);
ST(Bax, string);
int main() {
cout << Foo{3} << endl;
cout << Bar{5} << endl;
cout << Bax{"somthing"} << endl;
}
C++20 comment (EDIT)
I've not used c++ much lately, so I'm sorry if this isn't 100% correct. There's a comment about why this wouldn't be an issue in c++20. According to the reference on template_parameters:
A non-type template parameter must have a structural type, which is one of the following types (optionally cv-qualified, the qualifiers are ignored):
...
a floating-point type;
a literal class type with the following properties:
all base classes and non-static data members are public and non-mutable and
the types of all base classes and non-static data members are structural types or (possibly multi-dimensional) array thereof.
This had led me to believe that the following code would work:
struct conststr
{
const char * const p;
template<std::size_t N>
constexpr conststr(const char(&a)[N]) : p(a)/*, sz(N - 1) */{}
};
template<conststr s>
struct A{};
int main(int argc, char **argv) {
A<conststr("foo")> x;
}
(Again, I'm not 100% sure if that's 100% correct). But it doesn't, at least not on my machine with g++ -std=c++2a (g++ --version == g++ (Debian 8.3.0-6) 8.3.0). It doesn't work with double either. This guy gives a much more detailed account of the history here, and there are probably better references, and I could just be completely incorrect.
This works for classes and, IMO, is useful. The implementation is quick and dirty but can easily be made cleaner:
#include <stdio.h>
#include <string.h>
struct TextTag { const char *text; };
template <const TextTag &TRUE, const TextTag &FALSE>
struct TextTaggedBool
{
const char *GetAsText() const { return m_value ? TRUE.text: FALSE.text; }
void SetByText(const char *s) { m_value = !strcmp(s, TRUE.text); }
bool m_value;
};
class Foo
{
public:
void method()
{
m_tbool.SetByText("True!"); printf("%s\n", m_tbool.GetAsText());
m_tbool.SetByText("False!"); printf("%s\n", m_tbool.GetAsText());
m_tbool.m_value = true; printf("%s\n", m_tbool.GetAsText());
m_tbool.m_value = false; printf("%s\n", m_tbool.GetAsText());
}
private:
static constexpr TextTag TrueTag = { "True!" };
static constexpr TextTag FalseTag = { "False!" };
TextTaggedBool<TrueTag, FalseTag> m_tbool;
};
void main() { Foo().method(); }
Output:
True!
False!
True!
False!
Related
I'm hoping there's a way to write a single get function for a class with a large number of accessible (but non-editable) data members, of mixed type. Use of a map holding void*-cast copies of the members' addresses will work, as seen in the following code, but as soon as a 'const' is thrown in to the mix to enforce read-only, unsurprisingly C++ barks saying that 'const void*' type cannot be recast in order to appropriately access the data member. The following code works for writing a single get function for a class of mixed data types, but it effectively makes all data members accessed by the get function public (see specifically the get function in the memlist class).
Bottom line:
Is there a way to make a pointer type-castable while retaining read-only at the actual memory location? Or more fundamentally, can one define a type cast-able pointer to a constant variable? E.g., it seems to me that const type *var defines a read-only/non-castable address to a read-only variable, whereas I am trying to find something (that hasn't worked for me as of yet) more like type * const var, though I haven't been able to find any documentation on this.
#include <iostream>
#include <string>
#include <map>
class A{
public:
A(int a, double b): a(a), b(b) {};
private:
int a;
double b;
friend std::ostream& operator<<(std::ostream& os, A& rhs);
};
class memlist{
public:
memlist(int param1, double param2)
{
myint = new int(param1);
mydouble = new double(param2);
myclass = new A(param1,param2);
getMap["myint"] = myint;
getMap["mydouble"] = mydouble;
getMap["myclass"] = myclass;
}
~memlist()
{
delete myint;
delete mydouble;
delete myclass;
}
void* get(std::string param) {return getMap[param];};
private:
int *myint;
double *mydouble;
A *myclass;
std::map<std::string,void*> getMap;
};
std::ostream& operator<<(std::ostream& os, A& rhs){
os << rhs.a << std::endl << rhs.b;
return os;
};
int main(){
int myint = 5;
double mydbl = 3.14159263;
memlist mymem(myint,mydbl);
std::cout << *(int*)mymem.get("myint") << std::endl;
std::cout << *(double*)mymem.get("mydouble") << std::endl;
std::cout << *(A*)mymem.get("myclass") << std::endl;
*(int*)mymem.get("myint") = 10;
std::cout << *(int*)mymem.get("myint") << std::endl;
return 0;
}
Output:
5
3.14159
5
3.14159
10
The code shown is very, shall we say, ill-designed.
void* is as close to destroying the type system as it gets in C++. As mentioned in the comments, std::any is a better solution to this.
That said, I took it as a challenge to implement what you have illustrated in the question in a type-safe manner. It was overkill, to say the least.
#include <iostream>
#include <type_traits>
using namespace std;
template<typename>
struct is_str_literal : false_type {};
template<size_t N>
struct is_str_literal<const char[N]> : true_type {};
template<typename T>
struct is_str_literal<T&> : is_str_literal<T> {};
template<typename T>
constexpr bool is_str_literal_v = is_str_literal<T>::value;
constexpr bool samestr(const char* arr1, const char* arr2, size_t n)
{
return n == 0 ? arr1[0] == arr2[0] :
(arr1[n] == arr2[n]) && samestr(arr1, arr2, n - 1);
}
template<size_t N1, size_t N2>
constexpr bool samestr(const char (&arr1)[N1], const char (&arr2)[N2])
{
return N1 == N2 ? samestr(arr1, arr2, N1 - 1) : false;
}
constexpr char myint[] = "myint";
constexpr char mydouble[] = "mydouble";
constexpr char myclass[] = "myclass";
struct S
{
template<const auto& name>
const auto& get()
{
static_assert(is_str_literal_v<decltype(name)>, "usage: get<var name>()");
if constexpr(samestr(name, ::myint))
return myint;
if constexpr(samestr(name, ::mydouble))
return mydouble;
if constexpr(samestr(name, ::myclass))
return myclass;
}
int myint;
double mydouble;
char myclass;
};
int main()
{
S s;
s.myint = 42;
s.mydouble = 10.0;
s.myclass = 'c';
cout << s.get<myint>() << endl;
cout << s.get<mydouble>() << endl;
cout << s.get<myclass>() << endl;
}
Live
This uses C++17.
After some further poking around, I have to respectfully disagree with the previous assessments in the comments and answers... I have, since posting this question, come across many functions in the standard C library where void * types are readily used (http://www.cplusplus.com/reference/cstdlib/qsort/), not to mention it being the return type of malloc (probably the most widely-used function in C/C++?) which relies on programmer type-casting. Also, to the best of my knowledge, std::any is a new c++17 class, so how might you have answered this question 6 months ago?
I am trying to design a class which all its data is constant and know at compile time. I could just create this by manually typing it all but I want to use a template so that I don't have to rewrite almost the same code many times.
I was thinking templates are the way to do this e.g
template<class T> class A { ... }
A<float>
A<MyObject>
A<int>
But then I wasn't sure how I could get the constant data that I know into this object. I could do it at run-time with a member function which does a switch statement on the type or something similar but I ideally want it to effectively be a dumb data holder for me to use.
So in the case of A<float> I would have this:
// member function
int getSize() {
return 4;
}
Instead of (pseudo code)
// member function
int getSize() {
if (type == float) {
return 4;
} else if ...
}
I'm wondering if there is a known way to do this? I don't have any experience with constexpr, could that be the key to this?
edit: To clarify: I want member functions which always return the same result based on the templated type/class. For example, A would always return 4 from getSize() and 1 from getSomethingElse() and 6.2 from getAnotherThing(). Where as A would return 8 from getSize() and 2 from getSomethingElse() and 8.4 from getAnotherThing().
You can have this template
template <int size_, int foo_, int bar_>
struct MyConstData {
static const int size = size_; // etc
};
Then specialize your template:
template <class T> class A;
template <> class A<float> : MyConstData<13,42,-1> {};
template <> class A<double> : MyConstData<0,0,42> {};
You can specialize particular functions within a class, and given your description of things, I suspect that's what you want. Here is an example of how this works:
#include <iostream>
#include <string>
template <class T>
class A {
public:
int MyConstantFunction() const { // Default implementation
return 0;
}
};
template <>
int A<int>::MyConstantFunction() const
{
return 3;
}
template <>
int A<float>::MyConstantFunction() const
{
return 5; // If you examine the world, you'll find that 5's are everywhere.
}
template <>
int A<double>::MyConstantFunction() const
{
return -5;
}
int main(int, char *[])
{
using ::std::cout;
A<int> aint;
A<float> afloat;
A<long> along;
cout << "aint.MyConstantFunction() == " << aint.MyConstantFunction() << '\n';
cout << "afloat.MyConstantFunction() == "
<< afloat.MyConstantFunction() << '\n';
cout << "along.MyConstantFunction() == "
<< along.MyConstantFunction() << '\n';
return 0;
}
Notice how along just used the default implementation from the class declaration. And this highlights a danger here. If the translation unit using your specialization for a given type hasn't seen that specialization, it won't use it, and that may cause all kinds of interesting problems. Make sure this happens.
The other option is to not provide a default implementation at all, and so you get an instantiation error.
My gut feeling is that you are doing something that is pointless and a poor design. But, since I don't know the full context I can't say that for sure. If you insist on doing this, here's how.
If you want to implement different things depending on the type, you could try this:
template <class T>
class Foo {
T data;
string toString() {
return myGeneralToString(data);
}
};
template <>
class Foo<string> {
string data;
string toString() {
return "Already a string: " + data;
}
};
If you just want templated constants, I'd try this:
template <int a, int b>
class Calc {
public:
static constexpr int SUM = a + b;
};
int main()
{
std::cout << Calc<3, 5>::SUM << std::endl;
return 0;
}
Edit: as pointed out by Omnifarious C++14 has templated constants without templating the class itself. So you could simplify the example to:
class Calc {
public:
template <int a, int b>
static constexpr int SUM = a + b;
};
int main()
{
std::cout << Calc::SUM<3, 5> << std::endl;
return 0;
}
I'd like a constexpr function that will return me a unique id for every C++ type, something like this:
using typeid_t = uintptr_t;
template <typename T>
constexpr typeid_t type_id() noexcept
{
return typeid_t(type_id<T>);
}
int main()
{
::std::cout << ::std::integral_constant<typeid_t, type_id<float>()>{} << ::std::endl;
return 0;
}
But I get an error:
t.cpp: In function 'int main()':
t.cpp:23:69: error: conversion from pointer type 'typeid_t (*)() noexcept {aka long unsigned int (*)() noexcept}' to arithmetic type 'typeid_t {aka long unsigned int}' in a constant-expression
::std::cout << ::std::integral_constant<typeid_t, type_id<float>()>{} << ::std::endl;
^
t.cpp:23:69: note: in template argument for type 'long unsigned int'
Is there a workaround or another way?
You could use some tricks as shown in this answer.
There's even a library called ctti that utilizes the same trick, it should work out of the box
static_assert(ctti::type_id<int>() != ctti::type_id<float>(), "compile-time type-id comparison");
constexpr auto hash = ctti::type_id<int>().hash();
Another way, this time involving a constexpr function, would be to use a well known hash function like in the following example (where I used the FNV v1a):
#include <cstdint>
#include <iostream>
static constexpr uint32_t offset = 2166136261u;
static constexpr uint32_t prime = 16777619u;
constexpr uint32_t helper(uint32_t partial, const char *str) {
return str[0] == 0 ? partial : helper((partial^str[0])*prime, str+1);
}
constexpr uint32_t hash_str(const char *input) {
return helper(offset, input);
}
struct MyClassA { static constexpr uint32_t type = hash_str("MyClassA"); };
struct MyClassB { static constexpr uint32_t type = hash_str("MyClassB"); };
int main() {
std::cout << "MyClassA: " << MyClassA::type << std::endl;
std::cout << "MyClassB: " << MyClassB::type << std::endl;
}
The drawbacks:
conflicts can happen
error-prone (at least, from my point of view)
pretty invasive a sollution
The main advantage is that you can use this solution if you need the types to be the same over different executions (as an example, if you have to store them somewhere and use them again after a while).
This's not a constexpr function, but if there is not the constraint for the types to be persistent over multiple executions, you can use CRTP idiom as an alternative approach to achieve the same result.
It follows a minimal, working example:
#include <cstddef>
#include <iostream>
struct BaseClass {
protected:
static std::size_t next() noexcept {
static std::size_t counter = 0;
return counter++;
}
};
template<class D>
struct Base: public BaseClass {
static std::size_t type() noexcept {
static std::size_t type_ = BaseClass::next();
return type_;
}
};
struct A: public Base<A> { };
struct B: public Base<B> { };
int main() {
std::cout << A::type() << std::endl;
std::cout << B::type() << std::endl;
}
This way you have a base class from which to derive for all those types for which you would like to have an unique identifier.
What's wrong with the code below? Latest version of g++ and clang both give error. I am sure I am missing something basic here.
#include <iostream>
struct Z
{
static const int mysize = 10;
};
Z f2();
int main()
{
std::cout << f2()::mysize << std::endl;
}
The motivation here is to be able to find out the size of an array using templates using code such as below. I know there are many ways, but just stumbled upon this idea.
template<int N> struct S
{
enum { mysize = N };
};
template<class T, int N> S<N> f(T (&)[N]);
int main()
{
char buf[10];
std::cout << f(buf)::mysize << std::endl;
}
f2() returns a value, not a type. You'd need to use the . operator on the return value instead of ::
The :: operator requires a type to be named on the lefthand side, while . allows for a value to be named. Your expression f2() does not name a type so it cannot be used in conjunction with ::.
As a side note, with a little more detail in the question we might be able to solve your real problem.
Your program contains two mistakes:
You are using the :: operator to access the member of an object. Use operator . ("dot") instead;
You declare function f2() and invoke it without defining it (this will give you a linker error).
Also, since static member variables are shared among all instances of a class (Z in this case), you do not need an object to access it;
Here is how you could fix your program:
#include <iostream>
struct Z
{
static const int mysize = 10;
};
Z f2() { return Z(); }
int main()
{
// Don't need an object to access a static variable...
std::cout << Z::mysize << std::endl;
// ...but if you really want to, do it this way...
std::cout << f2().mysize << std::endl;
}
Why don't you use this way to find out the size of array by templates:
#include <iostream>
template<int N> struct S
{
enum { mysize = N };
};
template<class T, int N> int f1(T (&)[N])
{
return N;
}
int main()
{
char buf[10];
std::cout << f1(buf) << std::endl;
}
And this one is closer to your variant:
template<class T, int N> S<N> f(T (&)[N])
{
S<N> foo;
return foo;
}
int main()
{
char buf[10];
std::cout << f(buf).mysize << std::endl;
}
Anyway, you will need to return an object from f and access it's member by ., not by ::.
But it's more probable that second variant will be slower, because first variant is fully compile-time, but in the second variant compiler may miss the optimization and don't optimize out the run-time creation of foo.
I think you need to add const int Z::mysize; after class declaration.
I was wondering if it is possible to change the return type of a function based on the type of variable it is being assigned to. Here's a quick example of what I mean.
I want to create a function that parses a variable of int, bool, or float from a string. For example...
Int value = parse("37");
Float value = parse("3.14");
Bool value = parse("true");
I understand if I make this function a template, that the variable type must be determined from the argument list which is always going to be a string. Is there any other way of doing this with c++?
This can be done with a conversion function
struct proxy {
string str;
proxy(string const &str):str(str) { }
template<typename T> operator T() {
return boost::lexical_cast<T>(str);
}
};
proxy parse(string const &str) { return proxy(str); }
Now you just need to do
float a = parse("3.1");
And it should work well. Incidentally, you may just use the class directly. I recommend renaming it to conversion_proxy to point to the fact that it's just a proxy to a happening conversion but that it itself doesn't do conversion
struct conversion_proxy {
string str;
conversion_proxy(string const &str):str(str) { }
template<typename T> operator T() {
return boost::lexical_cast<T>(str);
}
};
float a = conversion_proxy("3.1");
I can't tell from your question if you know this or not, but you can indeed do this with a template. The only catch is that you will have to specify the type that you are converting from in each invocation instead of relying on inference (since as you said the argument type will always be the same).
template<typename T> T parse(const string& str) { /* do stuff for other types */ }
template<> int parse<int>(const string& str) { /* do stuff for ints */ }
template<> double parse<double>(const string& str) { /* do stuff for doubles */ }
template<> bool parse<bool>(const string& str) { /* do stuff for bools */ }
// etc.
And then invoke as
int value = parse<int>("37");
double value = parse<double>("3.14");
bool value = parse<bool>("true");
If you already knew this just ignore this answer, but it's not clear from your question that you are aware that this is possible.
Of course, if what you're doing isn't really generic (and so you have to specialize for each type you want to parse) then writing a template isn't the right thing to do anyway.
By the way, you can do it pretty generically with a single function like this (assuming parse is what you really want to do):
#include <sstream>
template<typename T> T parse(const string& str)
{
T t;
std::istringstream sstr(str);
sstr >> t;
return t;
}
This will work for any default-constructable, stream-extractable type, which includes all built-ins.
You could pass your output argument as a pointer or reference.
Like this:
template<class T> void parse(const std::string &input, T& output);
Then code like this:
double d; parse(input, d);
int i; parse(input, i);
should work.
However, your code looks like a perfect fit for an std::istringstream that would just be:
istringstream is(input);
input >> d;
If you have somewhat complicated formatting involved, a trick I have had pretty good luck with involves creating custom objects with custom operator>> that pulls out data.
Then it could be like:
istringstring is(input);
input >> LineExtracter(x, y, d);
I would agree with litb who was a little quicker than myself. Use the casting operators.
#include <iostream>
#include <string>
#include <sstream>
class Convertible
{
public:
int m_Integer;
bool m_Bool;
double m_Double;
Convertible() : m_Integer(0), m_Bool(false), m_Double(0.0) {};
operator int() const
{
return m_Integer;
}
operator bool() const
{
return m_Bool;
}
operator double() const
{
return m_Double;
}
};
Convertible parse(std::string data)
{
Convertible l_result;
std::istringstream converter(data);
converter >> l_result.m_Integer;
std::istringstream converter2(data);
converter2 >> l_result.m_Bool;
std::istringstream converter3(data);
converter3 >> l_result.m_Double;
return l_result;
}
void main()
{
int l_convertedInt = parse("2");
bool l_convertedBool = parse("true");
double l_convertedDouble = parse("3.14");
std::cout << "Converted '2' to " << l_convertedInt << std::endl;
std::cout << "Converted 'true' to " << l_convertedBool << std::endl;
std::cout << "Converted '3.14' to " << l_convertedDouble << std::endl;
}
Unfortunately, that isn't possible. In C++ it is not possible to overload a function based on it's return value. You either have to have 3 functions, ParseInt, ParseFloat, and ParseBool, or use a function template.
You could return void* and then cast the result as needed.
I advise against this though. C++ is a strongly typed language. The advantage of this is that the compiler can catch errors earlier than a dynamically typed language.
No this type of behavior is not possible in C++. To be allowable it would necessitate being able to define functions of the same name at the same scope that differed only by return type. This is not legal in C++.
C++ can do some return type specialization such as covariant return types on overridden virtual functions. But it does not support what you are looking for.
Here's my adaptation of #Tyler McHenry's answer for my situation where the argument to parse() is a type other than a string.
Note that I found I had to introduce a template specialization in order to avoid a type conversion warning (float to int).
(Also see live demo.)
#include <iostream>
struct MyUnion
{
public:
union {
bool bool_value;
int int_value;
float float_value;
};
};
template<typename T> T parse(const MyUnion& h)
{
T t;
if (typeid(T) == typeid(bool)) {
t = h.bool_value;
} else if (typeid(T) == typeid(int)) {
t = h.int_value;
} else if (typeid(T) == typeid(float)) {
// t = h.float_value; // see **Warning** below; use float specialization instead
}
return t;
}
// 'float' template specialization to avoid conversion warning.
template<> float parse(const MyUnion& h)
{
return h.float_value;
}
int main()
{
MyUnion mu1; mu1.bool_value = true;
MyUnion mu2; mu2.int_value = 42;
MyUnion mu3; mu3.float_value = 3.14159;
std::cout << "As bool: " << parse<bool>(mu1) << std::endl;
std::cout << "As int: " << parse<int>(mu2) << std::endl;
std::cout << "As float: " << parse<float>(mu3) << std::endl;
}
// **Warning**
// In function 'T parse(const Heterogeneous&) [with T = int]':
// Line 22: warning: converting to 'int' from 'const float'