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");
Related
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.
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.
recently I've tried to take advantage of C++0x constexpr under MSVC 2015 and my objective was to achieve compile-time hash strings. I wrote a simple FNV-1a hash algorithm as a constexpr function using, as required, a single return statement (ternary operator) and calling only constexpr functions, here it is:
template <size_t N>
constexpr U32 StringID_FNV1a_32(const char(&str)[N], I32 charIndex = 0, U32 hash = 2166136261U)
{
return charIndex < N-1 ? StringID_FNV1a_32(str, charIndex +1, (hash ^ str[charIndex]) * 16777619U) : hash;
}
I also made a little macro to be able to change the algorithm under the hood without any trouble:
#define STRING_ID(str) core::utility::StringID_FNV1a_32(str)
then I used this macro in my code, carefully checking if any breakpoint was hit and, also, the generated assembly code. Here's the little scenario:
//1. normal variable test
U32 hash1 = STRING_ID("abc");
//2. enum test
enum {
hash2 = STRING_ID("abc")
};
//3. constexpr variable test
constexpr U32 hash3 = STRING_ID("abc");
And here the facts:
first test was called at run time
second test was performed at compile time
third test was called at run time
As you can imagine I'm a little confused about the first and the third attempt.
Why in the third scenario is the compiler allowed to call the function at runtime? even though the msdn says clearly "The primary difference between const and constexpr variables is that the initialization of a const variable can be deferred until run time whereas a constexpr variable must be initialized at compile time." [https://msdn.microsoft.com/it-it/library/dn956974.aspx#Anchor_3]
Can be related to the fact that I'm in debug mode with all the optimizations turned off? and what about the first test?, is there any way to force the compiler to perform the hash at compile time?
MSVC's behavior can be quite strange, however it is possible to force it to make constexpr functions run at compile time.
#define COMPILE_TIME(value) ((decltype(value))CompileTime<decltype(value), value>::ValueHolder::VALUE)
template<typename T, T Value>
struct CompileTime
{
enum class ValueHolder : T
{
VALUE = Value
};
};
This forces the value to be passed as a template argument + an enumeration value, thus making it strictly compile-time only. Also please note that this works only for integer types.
You can use it simply by putting the call to the constexpr function as a parameter to the COMPILE_TIME macro:
constexpr U32 hash = COMPILE_TIME(STRING_ID("abc"));
I am unable to understand the use & purpose of the noexcept keyword in C++11/14. I understand that it is a signature for a function that does not emit exceptions. But does it really work?
Look at this code below :
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void seev (vector<int> &v) noexcept;
void seev (vector<int> &v) noexcept
{
for (int i=0;i<10;++i)
{
cout<<v.at(i)<<' ';
}
}
int main()
{
vector<int> v {1,2,3,4,5};
seev(v);
return 0;
}
The above code will surely throw an out_of_range exception. So the use of noexcept here is useless, or is it?
My queries are :
How does noexcept work?
How is it used?
What throw() wasn't able to do that noexcept could?
A noexcept specification on a function is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions.
The compiler can use this information to enable certain optimizations on non-throwing functions as well as enable the noexcept operator, which can check at compile time if a particular expression is declared to throw any exceptions.
For example, containers such as std::vector will move their elements if the elements' move constructor is noexcept, and copy otherwise (unless the copy constructor is not accessible, but a potentially throwing move constructor is, in which case the strong exception guarantee is waived).
noexcept is an improved version of throw(), which is deprecated in C++11. Unlike throw(), noexcept will not call std::unexpected and may or may not unwind the stack, which potentially allows the compiler to implement noexcept without the runtime overhead of throw().
For more details, please visit below websites
https://akrzemi1.wordpress.com/2014/04/24/noexcept-what-for/
When should I really use noexcept?
Edit: Sample source code to illustrate above points.
// whether foo is declared noexcept depends on if the expression
// T() will throw any exceptions, check in compile time
template <class T>
void foo() noexcept(noexcept(T())) {
}
void bar() noexcept(true) {
}
void baz() noexcept {
throw 42;
} // noexcept is the same as noexcept(true)
int main()
{
foo<int>(); // noexcept(noexcept(int())) => noexcept(true), so this is fine
bar(); // fine
baz(); // compiles, but at runtime this calls std::terminate
}
I'm posting 2 pieces of code to explain your problem:
Code 1:
#include <iostream>
using namespace std;
void foo() noexcept // see the noexcept specifier
{
throw 42;
}
int main()
{
try
{
foo();
}
catch(...)
{
cerr<<"exception caught\n";
}
return 0;
}
Here the output will be :-
terminate called after throwing an instance of 'int'
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
If I remove the noexceptthen:
Code 2:
#include <iostream>
using namespace std;
void foo() // noexcept is eliminated
{
throw 42;
}
int main()
{
try
{
foo();
}
catch(...)
{
cerr<<"exception caught\n";
}
return 0;
}
Output will be :-
exception caught
Because foo was signed as noexcept, hence terminate was called.
Inheriting constructors and the implicitly-declared default constructors, copy constructors, move constructors, destructors, copy-assignment operators, and move-assignment operators are all noexcept(true) by default, unless they are required to call a function that is noexcept(false), in which case these functions are noexcept(false).
You can also write lines like:
cout << boolalpha << noexcept(foo); // here noexcept acts as
// an operator instead of a specifier
The above line will check if foo will throw an exception or not. If it would throw then the return value will be true else false.
You can read more about these in this: http://scottmeyers.blogspot.dk/2014/03/declare-functions-noexcept-whenever.html
noexcept indicates that a function is intended not to to throw an exception, a guarantee you as a developer provides, that is not enforced by the compiler. So using it in a situation where your function calls functions that might throw exceptions that you do not catch yourself is bad.
The whole range of throw() specifiers were removed because the exception specifiers were less than optimal in C++, see: Difference between C++03 throw() specifier C++11 noexcept
noexcept has the advantage of not stating which exception is thrown, but rather whether an exception is thrown or not. It accepts a parameter which may be false if you expect the function to throw an exception.
The uses of this, can be in for instance an inherited class structure, where one super class wish to "enforce" to an inherited class, that a specific virtual function is not allowed to throw an exception. Further more the compiler may use the information for optimization.
noexcept is also an operator which can evaluate an expression and return whether or not that expression may thrown an exception or not, as per § 5.3.7.
5.3.7 noexcept operator [expr.unary.noexcept]
1 The noexcept operator determines whether the evaluation of its operand, which is an unevaluated operand
(Clause 5), can throw an exception (15.1).
noexcept-expression:
noexcept ( expression )
2 The result of the noexcept operator is a constant of type bool and is an rvalue.
3 The result of the noexcept operator is false if in a potentially-evaluated context the expression would
contain
— a potentially-evaluated call to a function, member function, function pointer, or member function pointer that does not have a non-throwing exception-specification (15.4), unless the call is a constant
expression (5.19),
— a potentially-evaluated throw-expression (15.1),
— a potentially-evaluated dynamic_cast expression dynamic_cast(v), where T is a reference type, that requires a run-time check (5.2.7), or
— a potentially-evaluated typeid expression (5.2.8) applied to a glvalue expression whose type is a polymorphic class type (10.3).
Otherwise, the result is true.
I can't explain the possible optimizations as well as Scott Meyers: http://aristeia.com/EC++11-14/noexcept%202014-03-31.pdf from his blog post: Declare functions noexcept whenever possible?
The difference between unwinding the call stack and possibly unwinding it has a surprisingly large impact on code generation. In a noexcept function, optimizers need not keep the runtime stack in an unwindable state if an exception would propagate out of the function, nor must they ensure that objects in a noexcept function are destroyed in the inverse order of construction should an exception leave the function. The result is more opportunities for optimization, not only within the body of a noexcept function, but also at sites where the function is called. Such flexibility is present only for noexcept functions. Functions with “throw()” exception specifications lack it, as do functions with no exception specification at all.
With the advent of C++11, we have unordered_map.cbegin/cend to specifically return us values of const_iterator. so the deduced type of 'it' in the expression "auto it = unordered_map.cbegin()" is const_iterator.
However, when it comes to unordered_map.find(key) function, I think there may be missing a "cfind()" counterpart, which returns a const_iterator specifically.
Some say that we can use "const auto it = unordered_map.find(key)" to obtain a "const iterator", but I have a strong suspicion that "const iterator" is the same "const_iterator", where "const iterator" limits the ability to change the iterator itself, while "const_iterator" limits the ability to change the content the iterator is referring to.
So, really, if we want to take advantage of "auto" type deduction fully (with the knowledge of the confusions or the variations of "auto" type deduction - auto, auto&, const auto&, etc.), how can I have unordered_map.find(key) to return a "const_iterator" without me having to explicitly specify "const_iterator" - that's after all the best use case for auto!
Below is a simple example code that demonstrates the compiler behavior:
#include "stdafx.h"
#include <unordered_map>
int _tmain(int argc, _TCHAR* argv[])
{
typedef std::unordered_map<int, int> umiit;
umiit umii;
auto it0 = umii.find(0);
it0->second = 42;
const auto it1 = umii.find(0);
it1->second = 42;
umiit::const_iterator it2 = umii.find(0);
it2->second = 42; // expected compiler error: assigning to const
return 0;
}
I'm not aware of any place that takes a const_iterator where you couldn't simply pass an iterator instead, so this deficiency may not interfere much with day-to-day code writing. However, I do prefer to use const_iterators (and const in general) wherever I don't need mutating, in the interests of general communication, so I think adding a cfind() might be a useful addition to the future standard library.
I think this code could function as a simple workaround for what you're trying to achieve, though:
template<typename T>
auto use_as_const( T const &t ) -> T const & {
return t;
}
This is a simple casting wrapper function, similar in style to move() and forward<T>(), to provide (and document) a constraint on individual usages of the object. You could then use it like this:
auto it1 = use_as_const( umii ).find(0);
This could also be used instead of leaning on cbegin() and cend(). Or, it could be used in range-based for loops:
for ( auto &element : use_as_const( some_vector_of_string ) ) {
cout << element;
// element = ""; // This line shouldn't compile.
}
In the above loop example, although I would generally prefer auto const &element : ..., I believe it would be unnecessary and element would still be deduced to be a const reference.
It's a bit of a deficiency; we have cbegin and cend but no corresponding cfind, etc.
I'd suggest using a utility function to get a const reference to the object, as per the answer to forcing use of cbegin()/cend() in range-based for:
template<typename T> constexpr const T &as_const(T &t) { return t; }
auto it1 = as_const(umii).find(0);
it1->second = 42; // fails