This question already has answers here:
Arrow operator (->) in function heading
(3 answers)
Closed 4 years ago.
What is the syntax used here with '-> decltype' after the operator() signature and what is it for?
template<>
struct less<void>
{ // transparent functor for operator<
typedef int is_transparent;
template<class _Ty1,
class _Ty2>
constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
-> decltype(static_cast<_Ty1&&>(_Left)
< static_cast<_Ty2&&>(_Right))
{ // transparently apply operator< to operands
return (static_cast<_Ty1&&>(_Left)
< static_cast<_Ty2&&>(_Right));
}
};
this is the code from C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\xstddef line 276.
Why are the following two lines duplicated?
(static_cast<_Ty1&&>(_Left)
< static_cast<_Ty2&&>(_Right))
->decltype(static_cast<_Ty1&&>(_Left) returns the type of static_cast<_Ty1&&>(_Left) and declare it as the return type of the function.
E.G.
auto function(int x ) -> int and int function(int x ) are the same
Related
I'm trying to create a struct template with a variadic template type pack, that can deduct the sum of the size of all types passed in.
Below you find a simplified example, in the real-world context, the size computed is used to create further member objects.
template <typename... Types>
struct OverallSize
{
template <typename FirstType, typename... NextTypes>
static constexpr size_t sizesum() { return sizeof (FirstType) + sizesum<NextTypes...>(); }
template <typename LastType>
static constexpr size_t sizesum() { return sizeof (LastType); }
static constexpr size_t size = sizesum<Types...>();
};
// Should work e.g. like this
auto s = OverallSize<int, float, char>::size; // s will be 9 on x86-64
I'm used to this recursive parameter unpacking approach when it comes to argument lists and assumed this works as well with argument-less functions and explicit template specification. However I get the following error when compiling with clang
Call to 'sizesum' is ambiguous
...
Candidate function [with FirstType = unsigned long, NextTypes = <>]
Candidate function [with LastType = unsigned long]
So it seems as if the last recursion iteration doesn't work here – not sure why the compiler doesn't simply chose the most obvious choice: The one with only one template type – just as it would happen if there was an actual template argument passed to the function.
So, what do I have to do to make this compile and work as desired?
For C++14 you can use SFINAE:
template <
typename FirstType,
typename... NextTypes,
std::enable_if_t<sizeof...(NextTypes) >= 1>* = nullptr >
static constexpr size_t sizesum() {
return sizeof (FirstType) + sizesum<NextTypes...>();
}
this template will be considered only if parameters pack has size >= 1.
Demo
I have the following construct:
template <class... Args>
class some_class
{
public:
some_class() = default;
some_class(Args...) = delete;
~some_class() = default;
};
template<>
class some_class<void>
{
public:
some_class() = default;
~some_class() = default;
};
The reason for this is that I just want to allow the users to create objects using the default constructor, so for example:
some_class<int,float> b;
should work but
some_class<int,float> c(1,3.4);
should give me a compilation error.
At some point in time I also needed to create templates based on void hence, the specialization for void:
some_class<void> a;
But by mistake I have typed:
some_class<> d;
And suddenly my code stopped compiling and it gave me the error:
some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be
overloaded
some_class(Args...) = delete;
So here comes the question: I feel that I am wrong that I assume that some_class<> should be deduced to the void specialization... I just don't know why. Can please someone explain why some_class<> (ie: empty argument list) is different from some_class<void>? (A few lines from the standard will do :) )
https://ideone.com/o6u0D6
void is a type like any other (an incomplete type, to be precise). This means it can be used as a template argument for type template parameters normally. Taking your class template, these are all perfectly valid, and distinct, instantiations:
some_class<void>
some_class<void, void>
some_class<void, void, void>
some_class<void, char, void>
In the first case, the parameter pack Args has one element: void. In the second case, it has two elements: void and void. And so on.
This is quite different from the case some_class<>, in which case the parameter pack has zero elements. You can easily demonstrate this using sizeof...:
template <class... Pack>
struct Sizer
{
static constexpr size_t size = sizeof...(Pack);
};
int main()
{
std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl;
}
This will output:
0 1 2
[Live example]
I can't really think of a relevant part of the standard to quote. Perhaps this (C++11 [temp.variadic] 14.5.3/1):
A template parameter pack is a template parameter that accepts zero or more template arguments. [ Example:
template<class ... Types> struct Tuple { };
Tuple<> t0; // Types contains no arguments
Tuple<int> t1; // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
Tuple<0> error; // error: 0 is not a type
—end example ]
This looks like an issue in clang (I've already opened a bug here), but I'd like to be sure that I'm not doing a mistake.
Consider the following code:
#include <type_traits>
#include <cstddef>
template<std::size_t N, std::size_t M, std::enable_if_t<not (N>M)>* = nullptr> // (1)
struct S: public S<N+1, M> { };
template<std::size_t N>
struct S<N, N> { };
int main() {
S<0, 1> c{};
}
It fails to compile with the following error:
8 : error: non-type template argument specializes a template parameter with dependent type 'std::enable_if_t M)> *' (aka 'typename enable_if M), void>::type *')
struct S { };
The same code works as expected using the following line instead of (1):
template<std::size_t N, std::size_t M, typename = std::enable_if_t<not (N>M)>>
The SFINAE expression is almost the same. It is based on a specialization of std::enable_if_t and I would expect the same result (success or failure) for both of the examples.
Are my expectations wrong?
Note that GCC works fine in either cases.
I think this is a gcc bug actually, as a result of [temp.class.spec]:
The type of a template parameter corresponding to a specialized
non-type argument shall not be dependent on a parameter of the
specialization. [ Example:
template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error
template< int X, int (*array_ptr)[X] > class A {};
int array[5];
template< int X > class A<X,&array> { }; // error
—end example ]
In your example, the type of the 3rd template parameter is dependent on a parameter. When you swap it to typename = std::enable_if_t<...>, then this rule no longer applies.
Note: is there any reason to use SFINAE here anyway, as opposed to static_assert-ing?
This question already has answers here:
C++ lambda with captures as a function pointer
(9 answers)
Closed 7 years ago.
UPDATED: (Rephrased). I'm looking to boost the computation efficiency of my code by make an run-time assignment of a class member function to one of many functions conditional on other class members.
One recommended solution uses #include <functional> and function<void()>, as shown in the simple test example:
#include <iostream>
using namespace std;
struct Number {
int n;
function(void()) doIt;
Number(int i):n(i) {};
void makeFunc() {
auto _odd = [this]() { /* op specific to odd */ };
auto _even = [this]() { /* op specific to even */ };
// compiles but produces bloated code, not computatinally efficient
if (n%2) doIt = _odd;
else doIt = _even;
};
};
int main() {
int i;
cin >> i;
Number e(i);
e.makeFunc();
e.doIt();
};
I'm finding that the compiled code (i.e. debug assembly) is grotesquely complicated and presumably NOT computationally efficient (the desired goal).
Does someone have an alternative construct that would achieve the end goal of a computationally efficient means of conditionally defining, at run-time, a class member function.
A capturing lambda expression cannot be assigned to a regular function pointer like you have.
I suggest using
std::function<void()> doIt;
instead of
void (*doIt)();
This question already has answers here:
c++ vector initialization
(5 answers)
Closed 8 years ago.
I'm trying to initialize a vector in visual studio this way :
const vector <int> A {1,2,3,4,5};
and its giving me an error. The error says :
"error C2470: 'A' : looks like a function definition, but there is no parameter list; skipping apparent body"
Can anyone please tell me why i'm getting this error?
As I have mentioned that VS2012 does not support initializer_list and hence we get the compilation error. You can use the following to get the almost same thing.
#include<vector>
#include <iterator>
#include<iostream>
using namespace std;
int main() {
int arr[] = {1,2,3,4,5};
const std::vector <int> A(std::begin(arr), std::end(arr));
for(const auto& i: A)
std::cout<<i<<std::endl;
}
The way which you are using to initialize vector is not supported by C++98...
The support has been provided for initializer list constructor in C++11..
so instead you can use below code...
int arr[] = {1,2,3,4,5};
vector<int> A(arr, arr+sizeof(arr)/sizeof(arr[0]));