How to use static_assert inside of a constexpr - c++

I have a function that can be called on an enum, save for one value. I want to check statically that the function is not called with that value. I have the following (simplified) (c++11) code:
enum class Channel: char {
ALL = 0,
ONE = 1,
TWO = 2,
};
inline constexpr std::size_t zeroBasedChannelIndex(const Channel channel) {
static_assert(channel != Channel::ALL, "Channel::All doesn't map to an index");
// ^^^^^^^ error location
return static_cast<std::size_t>(channel) - 1;
}
I'm getting the following error though: the value of parameter "channel" (declared at line 16 of "/opt/kvanwel/Workspaces/acdipole/amplib/src/powersoft/kseries/datamodel/../constants/Channel.h") cannot be used as a constant
It looks to me that channel IS constant... but computer says no. What am I doing wrong here?

The comments above have told you what's wrong. The only thing you can do to get round this is to pass channel as a template parameter:
template <Channel channel> constexpr std::size_t zeroBasedChannelIndex () {
static_assert(channel != Channel::ALL, "Channel::All doesn't map to an index");
return static_cast<std::size_t>(channel) - 1;
}
But now, that parameter must be known at compile time (i.e., in practise, a constant, most likely) when calling the function.

Related

Calling a Function with integer [[mayb_unused]] macro and default argument boolean type parameter

I am writing a Function with 2 Parameters, 1st is integer type marked [[maybe_unused]] and 2nd is Boolean Type with Default Argument false.
int preOrderTraversial([[maybe_unused]] int searchData, bool forDisplay = false)
This is the function declaration. The function is used for pre-order Traversal in Binary Search Tree. I want to use the same function for Displaying the Tree and Traversing it for searching a Node with specific Data. But only for 1 of both problems at once. Not for searching AND displaying you see.
So, obviously, it works fine for the searching part but when I call the function for Displaying the function call looks like this:
preOrderTraversal(true)
or
bool forDisplay = true;
preOrderTraversal(forDisplay);
Now the Compiler (even with the parameter DECLARED as a BOOL) still considers this bool parameter as an int and uses it for searchData (integer) parameter of the function and not for the forDisplay (bool) parameter.
Is there a way to force or tell compiler which of both parameters I am trying to work with?
[[maybe_unused]] means that the function body may not use it, but the signature of the function always have it. Actually event the default value for the boolean does not modify the signature of your function; Thus your function always take 2 arguments, the first being a integer, and the second being a boolean (that may be set to the default if you didn't put it). You end up with calling:
bool forDisplay = true;
preOrderTraversal(/* integer searchData; bool geting casted to int */ forDisplay,
false /* the forDisplay (2nd param) default value*/);
which does not meet your expectations.
[EDIT]
how to overcome?
There is not builtin way to use named parameters in C++ but you may workaround using a helper class:
struct PreOrderTraversal {
bool _forDisplay = false;
int _searchData = 0; /* FIXME What is the default here? */
auto& forDisplay() { _forDisplay = true; return *this; }
auto& searchData(int x) { _searchData = x; return *this; }
void run() { if (_forDisplay) ;//do the right things
else ;// use data
}
};
then you can use it with:
PreOrderTraversal().forDisplay().run();
PreOrderTraversal().searchData(123).run();
This kinda mimics that named parameter feature.

How to implement a function that safely cast any larger type to a smaller type in C++ using templates?

I'm trying to write a function that checks if the variable being cast can fit in the destination type, and assert() if not. Right now this is what I came up with. I didn't test it yet. I would like to make the template figure out the type of the varible being passed automatically, with something like typeid, although I don't really know what typeid really is. Is that possible? Also, I don't know much about templates.
template<typename from_T, typename to_T>
static inline to_T safe_cast(from_T variable)
{
assert(variable >= std::numeric_limits<to_T>::min());
assert(variable <= std::numeric_limits<to_T>::max());
return static_cast<to_T>(variable);
}
Well, if that is actually some function that already does this that I don't know of I will be glad to hear.
C++ Core Guidelines already has a gsl::narrow
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
You can see the Microsoft implementation here
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
constexpr T narrow(U u) noexcept(false)
{
constexpr const bool is_different_signedness =
(std::is_signed<T>::value != std::is_signed<U>::value);
const T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u || (is_different_signedness && ((t < T{}) != (u < U{}))))
{
throw narrowing_error{};
}
return t;
}
You can see the explanation of the implementation on this SO post (it's for an older version of the implementation, but nothing substantially changed, so the answer still applies).

Write method with trailing return type to change based on method call?

I have a class titled Eclipse with a private struct member containing ~30 fields of various data types.
I have a method that will return a data field from the struct, based on a field number passed in as a parameter.
Seeing as the struct contains data of various types, I opted to use the auto keyword with a trailing return type based on a templated parameter. My method header is below.
template<typename TheType>
auto getColumnData(TheType toGet, int fieldNum) -> decltype(toGet) {
// switch statement to return fields based on fieldNum
}
If I want to return a column that is an int, I call getColumnData(0, 1);. The first parameter is only used to determine the return type of the method, and the second parameter determines the field number to return to the method caller.
Theoretically, this would cause the return type of getColumnData() to be int and return the first column (corresponding to the first field) of the struct. But I'm receiving this compilation error:
no viable conversion from returned value of type 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') to function return type 'decltype(toGet)' (aka 'int')`
I understand that if I were to call this method with an int as the first parameter, and a field number that corresponds to a field returning a std::string, there would be issues. But, based on checks in other classes, this case would never occur.
Is there any way that I can force my compiler to accept this code, even if it might not be correct for certain cases?
I know that I could just overload the method, but I'd rather not have multiple different methods for basically the same purpose if I can figure out how to accomplish the task in only one.
Also, if my understanding of any of this information seems incorrect, please let me know. I'm very new to C++, so I'm just learning these features as I go.
You cannot change a method's return type dynamically at runtime like you are attempting to do. Your first parameter is not a data type known at compile-time. It is just an integer that is populated at runtime, so you can't make compile-time decisions based on it at all.
A simple solution would be to use std::variant (C++17 or later) or boost::variant (C++11 and later) as the return type:
using FieldType = std:::variant<int, std::string>;
FieldType getColumnData(int fieldNum) {
// switch statement to return fields based on fieldNum
}
int i = std::get<int>(getColumnData(1));
std::string s = std::get<std::string>(getColumnData(2));
Otherwise, you would have to make the return type be a template parameter, not a method parameter:
template<typename TheType>
TheType getColumnData(int fieldNum) {
// switch statement to return fields based on fieldNum
}
But then you run into the problem that not all fields will be convertible to the return type (can't return a std::string field when an int is requested, etc), so you can't just switch on the fieldNum since it is not evaluated at compile-time.
You might be tempted to make the field number be a template parameter so it is constant at compile-time, and then specialize on it:
template<const int FieldNum>
auto getColumnData() { return 0; };
template<> int getColumnData<1>() { return private_struct.Field1; }
template<> std::string getColumnData<2>() { return private_struct.Field2; }
// etc...
int i = getColumnData<1>();
std::string s = getColumnData<2>();
But I get errors when I try to do that on a templated class method ("explicit specialization in non-namespace scope").
You might be tempted to do something like this, and hope the compiler optimizes away the unused branches:
template<const int FieldNum>
auto getColumnData() {
if (FieldNum == 1) return private_struct.Field1;
if (FieldNum == 2) return private_struct.Field2;
//etc...
return 0;
}
or
template<const int FieldNum>
auto getColumnData()
{
switch (FieldNum) {
case 1: return private_struct.Field1;
case 2: return private_struct.Field2;
// etc...
}
return 0;
};
int i = getColumnData<1>();
std::string s = getColumnData<2>();
But that doesn't work, either ("inconsistent deduction for auto return type" errors).

Calling constexpr function for bitset template parameter

I'm trying to type alias the std::bitset class where the template parameter N is calculated using a constexpr function. However, this approach seems to be running into a wall.
The code currently looks like this:
static constexpr std::size_t ComponentCount() noexcept {
return 3U;
}
static constexpr std::size_t TagCount() noexcept {
return 5U;
}
using Bitset = std::bitset<ComponentCount() + TagCount()>;
And the error I'm receiving is as follows:
1>error C2975: '_Bits': invalid template argument for 'std::bitset', expected compile-time constant expression
1> note: see declaration of '_Bits'
Thanks for your help.
As indicated in the comments by #MattWeber, using the current webcompiler.cloudapp.net with compiler version 19.00.23720.0 (built 20 January 2016) this small test program using your code
int main()
{
cout << Bitset{}.size() << "\n";
}
does output 8. So just grab the latest Visual Studio and check the compiler version (if it's greater than 19.00.23720.0 it should work).
As things turned out, I didn't include enough context in my original question. The problem ended up being a little more subtle.
Here's a more accurate representation of how my code looked:
template
<
typename ComponentList,
typename TagList,
typename SignatureList
>
struct Settings {
// ...
static constexpr std::size_t ComponentCount() noexcept {
return 3U;
}
static constexpr std::size_t TagCount() noexcept {
return 5U;
}
// ...
using Bitset = std::bitset<ComponentCount() + TagCount()>;
// ...
};
This approach seemed okay to me, and didn't provide me with any compiler warnings or anything. Just the compiler error mentioned in the original question.
However, when I simplified the problem further in an attempt to more accurately isolate the problem, I ended up with this:
struct Settings {
static constexpr std::size_t ComponentCount() noexcept {
return 3U;
}
static constexpr std::size_t TagCount() noexcept {
return 5U;
}
using Bitset = std::bitset<ComponentCount() + TagCount()>;
};
After doing this simplification (or more specifically, after removing the template parameters), VS2015 found the the error function call must have a constant value in a constant expression on both of the ComponentCount() and TagCount() function calls, and highlighted them in red. Apparently the compiler is unable to view static constexpr functions that are contained within the same struct as constant expressions? Weird. It might be trying to do the type aliasing before defining the const expressions.
The solution for the templated struct was as follows:
using ThisType = Settings<ComponentList, TagList, SignatureList>;
// ...
using Bitset = std::bitset<ThisType::ComponentCount() + ThisType::TagCount()>;
However, this approach doesn't work for the non-templated struct. See my other StackOverflow post for different approaches in that case.

C++ static compile error using templates

I have
template < typename threadFuncParamT >
class ThreadWrapper
{
public:
static int ThreadRoutineFunction(void* pParam);
int ExecuteThread();
ThreadWrapper(ThreadPool<threadFuncParamT> *pPool);
};
template<typename threadFuncParamT>
int ThreadWrapper<threadFuncParamT>::ThreadRoutineFunction(void* pParam)
{
ThreadWrapper<threadFuncParamT> *pWrapper = reinterpret_cast<ThreadWrapper<threadFuncParamT>*>(pParam);
if(pWrapper != NULL)
{
return pWrapper-ExecuteThread(); // Error here.
}
return 0;
}
template < typename threadFuncParamT >
ThreadWrapper<threadFuncParamT>::ThreadWrapper(ThreadPool<threadFuncParamT> *pPool)
{
ThreadWrapper<threadFuncParamT>::m_pThreadPool = pPool;
m_tbbThread = new tbb::tbb_thread(&(ThreadWrapper<threadFuncParamT>::ThreadRoutineFunction), this);
if (m_tbbThread->native_handle() == 0)
{
delete m_tbbThread;
m_tbbThread = NULL;
// TODO: throw execption here or raise assert.
}
}
I am getting error as below
Error 1 error C2352: 'ThreadWrapper::ExecuteThread' : illegal call of non-static member function
I am compiling on VS2010.
Can any one help me here how to get clear the error.
Thanks!
The problem is that your error line
return pWrapper-ExecuteThread(); // Error here.
misses an >; it should read
return pWrapper->ExecuteThread(); // Error here.
You're getting such a strange compile error since it's trying to perform a subtraction; the pointer pWrapper is treated as an integer, and the value returned by calling ExecuteThread() (which yields an int) is subtracted from that. However, ExecuteThread() is neither a global function nor a static member function - hence the compiler complains.
You're missing the > on the call. You want return pWrapper->ExecuteThread();
You're missing the ">"
It's
pWrapper->ExecuteThread()
not
pWrapper-ExecuteThread()
You can't call static member function with that syntax. Try doing the following instead:
static_cast<ThreadWrapper*>(pParam)->ExecuteThread();
Maybe superfluous, but an explanation: functions that are entry points for threads cannot be instance methods, they must be file-scope function or static methods. The common idiom is to pass a void pointer to a static/global thread startup routine, cast that pointer to the proper class type and use it to call the actual instance method that will be executed in anothre thread.