How to use constexpr in this case? - c++11

I try to write function with constexpr
constexpr QString c(const QString &columnName);
but it output issue:
enclosing class of constexpr non-static member function 'QString
DatabaseHandler::c(const QString&) const' is not a literal type
constexpr QString c(const QString &columnName);
I very bad know C++ 11 yet so cannot undestand this bug. What does it mean?
P.S. If I add static then it also output issue Invalid return type 'QString'.

constexpr functions require that their input arguments and their return type are literal types, and therefore must have at least one constexpr constructor. Qstring (i.e, the return type) does not, thus you get a compiler error.

Related

Is const keyword mandatory while declaring"constexpr char*" string?

The project that I have just started working on has many instances of following,
constexpr const char* str = "Some Character(s)";
I wanted to understand, is the "const" keyword in above statement not redundant, as constexpr is implicitly constant?
It is mandatory because it won't compile if you remove it. This code:
constexpr char *str = "Some Character(s)";
Produces the following error on x64 GCC 11.2 (link):
error: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
1 | constexpr char *str = "Some Character(s)";
| ^~~~~~~~~~~~~~~~~~~
The implied const is for the pointer itself so a redundant const would actually be this:
constexpr const char *const str = "Some Character(s)";
// ^~~~~
const and constexpr has diferent behaivours, as both has the same prefix, you may think that they are the same, but constexpr means that an atribute (or function, or whatever) will be done in compile time, and const means that that atribute won't be modified (it is an inmutable value, you can modify it, but thats undefined behaivour), but maybe can't be evaluated at compile time.
Also, in that particular case, you can't create an char *from an string literal since -std=c++17

How to constraint the parameter package type in c++11? And How to implement the template in cpp?

For the first quesion:
I want to write a function to concatenation the strings, and it can receive multiple strings;
#include <string>
#include <vector>
#include <type_traits>
template <class... Args, typename std::enable_if<std::is_same<typename std::decay<Args...>::type, std::string>::type>::type>
std::string foo(const std::string &first, const Args &... senconds) {
std::string delimiter = "$$";
std::string ret = first;
std::vector<std::string> vec{senconds...};
for (auto second = vec.rbegin(); second != vec.rend(); second++) {
ret = delimiter + *second + delimiter + ret;
}
return ret;
}
but when I invoke it like:
std::string name = "x";
name = foo(name, "xxx");
the compiler will throw an error:
error: no matching function for call to ‘foo(std::__cxx11::string&, const char [4])’
and there will be some note:
note: couldn't deduce template parameter ‘<anonymous>’
I think I should modify the constraint in the template, and I've tried all the related methods in the type_traits, but none of them works.
For the second question:
I want to hide the implementation of some function, but for the template function, it's unable to put the definition in the .hpp, and put the implementation in the .cpp, the compiler will throw a undefined reference error. Is there any elegant way to solve this?
Thanks.
There's a bit to unwrap here.
std::decay<Args...>::type can't work. std::decay takes only a single template argument, but you attempt to expand the pack here. The expansion needs to happen on the is_same.
You are also missing a way to aggregate all the is_same predicates. Do you want to and them all or or them all? Presumably and. In C++17 that's easily done with a fold expression, but for C++11 we have to work a bit.
Finally the thing the compiler complains about: std::enable_if<bla>::type evaluates to void if bla is true. That means you're formally expecting a non-type template argument, and the compiler complains because it can't deduce which value of type void it should deduce. This is normally alleviated by forming a pointer to it instead and defaulting it to nullptr: std::enable_if<bla>::type* = nullptr.
It appears (?) that you expect foo(someString, "stringLiteral"); to work. It won't, because a string literal is not a std::string. Maybe you wanted a different predicate, but for this answer I'll stick with the original condition.
Putting all that together:
In C++17, you would write
template <class... Args,
std::enable_if_t<
(std::is_same_v<std::decay_t<Args>, std::string> && ...)
>* = nullptr
>
https://godbolt.org/z/84Dcmt
In C++11, we use this helper and add back the typename and ::type verbosity:
template <class... Args,
typename std::enable_if<
var_and<
std::is_same<typename std::decay<Args>::type, std::string>::value...
>::value
>::type* = nullptr
>
https://godbolt.org/z/2eFyX7
Base on MaxLanghof's answer, I changed the template to:
template <class... Args,
typename std::enable_if<var_and<std::is_constructible<
std::string, Args>::value...>::value>::type * = nullptr>
In this form, the function foo can be invoked like the name = foo(name, stringRed, "xxx").
Thanks #MaxLanghof again.

Optional throw in constexpr?

I was researching how to implement a compile time strlen for a toy project in this repo https://github.com/elbeno/constexpr when I noticed an unusual pattern of throws in some of the code. It seemingly does nothing, why would you do this?
namespace err {
extern const char * strlen_runtime_error;
}
constexpr int strlen(const char * str) {
return true ? constexpr_func() : throw strlen_runtime_error;
}
I got curious if it has any use what so ever but couldn’t find anything useful on my own. The extern err is undefined.
It seems it is trying to enforce the function being used only in compile time, according to this comment in another of the functions of the library:
// convenience function for inferring the string size and ensuring no
// accidental runtime encryption
template <uint64_t S, size_t N>
constexpr encrypted_string<S, N> make_encrypted_string(const char(&s)[N])
{
return true ? encrypted_string<S, N>(s) :
throw err::strenc_runtime_error;
}
However, as you point out, it is not doing anything here. Typically, that trick with the ternary operator in constexpr functions is used to trigger compile-time errors given a condition -- not to ensure all calls to the function are constant expressions. See constexpr error at compile-time, but no overhead at run-time for an explanation of that pattern.
If you need to ensure that the result was found out during compile time, you can easily assign the result to a constexpr variable:
constexpr int result = strlen("asd");

C++11, Is it possible to force an instance to be extern but also a constant expression of a non-type template parameter?

Using C++11, g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18).
Lets pretend I have a templated function (pardon my terminology if it isn't quite right).
I want to perform a "general" algorithm based on what was supposed to be compile-time instances of "field". Where the only things that really changed are these constants which I moved into trait classes (only added one here but imagine there are more). Originally I was declaring it as
constexpr field FIELD1{1};
However in C++11, non-type template params need to have external linkage (unlike C++14 which can have internal and external linkage?). So because not's in the same translation unit I needed to use extern in order to give it external linkage (sorry if I butchered that explanation also). But by defining it extern I can't define it using constexpr and it seems that losing that constexpr constructor this field is no longer a valid constant expression to qualify as a non-type template param.
Any suggestions if there is some way I can get around this? Open to a new method of doing things. Below is a simplified (incomplete, and non-compiling version to get the gist of the organization).
So the error I am seeing is along the lines of
error: the value of ‘FIELD1’ is not usable in a constant expression
note: ‘FIELD1’ was not declared ‘constexpr’
extern const field FIELD1;
Not quite sure what could be a best alternative.
I can get rid of the second error by removing the constexpr from the constructor. But then I don't know how to approach the constant expression issue.
field.H
struct field
{
int thingone;
constexpr field(int i):thingone(i){}
};
extern const field FIELD1;
field.C
#include "field.H"
const field FIELD1{0};
field_traits.H
#include "field.H"
template< const field& T >
class fieldTraits;
template< >
class fieldTraits<FIELD1>
{
public:
// Let's say I have common field names
// with different constants that I want to plug
// into the "function_name" algorithm
static constexpr size_t field_val = 1;
};
function.H
#include "field.H"
template< const field& T, typename TT = fieldTraits<T> >
void function_name()
{
// Let's pretend I'm doing something useful with that data
std::cout << T.thingone << std::endl;
std::cout << TT::field_val << std::endl;
}
So because not's in the same translation unit I needed to use extern in order to give it external linkage (sorry if I butchered that explanation also). But by defining it extern I can't define it using constexpr [...]
Per my comment, you can. It wouldn't work for you, but it's a step that helps in coming up with something that would work:
extern constexpr int i = 10;
This is perfectly valid, gives i external linkage, and makes i usable in constant expressions.
But it doesn't allow multiple definitions, so it can't work in a header file which is included in multiple translation units.
Ordinarily, the way around that is with inline:
extern inline constexpr int i = 10;
But variables cannot be declared inline in C++11.
Except... when they don't need to be declared inline because the effect has already been achieved implicitly:
struct S {
static constexpr int i = 10;
};
Now, S::i has external linkage and is usable in constant expressions!
You may not even need to define your own class for this, depending on the constant's type: consider std::integral_constant. You can write
using i = std::integral_constant<int, 10>;
and now i::value will do exactly what you want.

Is this change in overload resolution between Clang 3.5 and 3.6 correct or a bug?

The code below compiles in Visual Studio 2013, gcc 4.8, clang 3.4 and clang 3.5 (Apple LLVM 6.0) but does not compile in clang 3.6 (via Apple LLVM 6.1)
The code is a simplified version of a complicated class in our codebase which is the minimum required to exhibit the issue.
The crux of the problem is that the copy construction of TYPED_VALUE is, in 3.6, evaluating the templated conversion operator for type STRING because of the presence of a constructor that accepts a STRING; this causes std::is_constructible to be evaluated which leads to it needing the definition of STRING (which we cannot provide here - would lead to a circular dependency in the full code).
class STRING;
class TYPED_VALUE
{
public:
TYPED_VALUE( const TYPED_VALUE& ) = default; // explicit or implicit doesn't make a difference
TYPED_VALUE( const STRING & ) {}
template< typename TYPE, typename std::enable_if<!std::is_pointer< TYPE >::value && !std::is_constructible< TYPE, const STRING& >::value && !std::is_constructible< TYPE, bool >::value, int >::type = 0 >
operator TYPE( void ) const = delete;
};
class TYPED_STORAGE
{
public:
TYPED_STORAGE( const TYPED_VALUE &v ) : value( v ) {}
TYPED_VALUE value;
};
The error message is
/type_traits:2329:38: error: incomplete type 'SICORE::STRING' used in type trait expression
: public integral_constant<bool, __is_constructible(_Tp, _Args...)>
^
/main.cpp:348:99: note: in instantiation of template class 'std::__1::is_constructible<SICORE::STRING, const SICORE::STRING &>' requested here
template< typename TYPE, typename std::enable_if<!std::is_pointer< TYPE >::value && !std::is_constructible< TYPE, const STRING& >::value && !std::is_constructible< TYPE, bool >::value, int >::type = 0 >
^
/main.cpp:349:9: note: while substituting prior template arguments into non-type template parameter [with TYPE = SICORE::STRING]
operator TYPE( void ) const = delete;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
/main.cpp:355:56: note: while substituting deduced template arguments into function template 'operator type-parameter-0-0' [with TYPE = SICORE::STRING, $1 = (no value)]
TYPED_STORAGE( const TYPED_VALUE &v ) : value( v ) {}
^
/main.cpp:340:11: note: forward declaration of 'SICORE::STRING'
class STRING;
^
To me this seems like a bug in 3.6, in previous versions the overload resolution determines that the copy constructor is the best fit without having to evaluate the template arguments - I tried to understand the overload resolution notes in the standard but I think that just confused me more ;)
(This can be fixed by making either the constructor or the conversion operator explicit I realise, but that is not the behaviour we want)
Any standard experts out there know the answer?
I believe Clang is correct to produce this error:
The [temp.inst] section of the C++ standard in paragraph 10 says:
If a function template or a member function template specialization is
used in a way that involves overload resolution, a declaration of the
specialization is implicitly instantiated (14.8.3).
Forming the implicit conversion sequence necessary to rank the overload candidates for the call to TYPE_VALUE's constructor requires the instantiation of the conversion operator. And the use of an incomplete type parameter to the trait doesn't form an invalid type, so this isn't a substitution failure, it is a hard error.
The copy constructor of TYPED_VALUE uses a reference to STRING, it should not be evaluated.
I think this is a clang error.
I haven't read the new c++ standard for a long time, however, I couldn't make sure it hadn't changed.
templates are instantiated as-needed, and I think Clang 3.6 implemented a DR where it needed to instantiate a template earlier than 3.5 did.

Resources