Getting the length of an array. Compiler errors. - c++

I've tried:
template <typename T,unsigned S>
unsigned getArraySize(const T (&v)[S]) { return S; }
after Motti's answer https://stackoverflow.com/a/18078435/512225
but I've got this message:
error C2265: '' : reference to a zero-sized array is illegal
What's wrong with my compiler?
I gave a look at this page:
http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/4b78bcef-4c33-42f1-a4c5-fb6f702ced0b/vs6-c-compile-error-using-getaddrinfo
so I tried this solution:
template <typename T,unsigned S>
unsigned getArraySize(const T v[S]) { return S; }
this compiles, but when I try to use it:
double myX[2] = {7,3};
std::cout << getArraySize(myX) << std::endl;
I get a compilation error:
error C2783: 'unsigned int __cdecl getArraySize(const T [])' : could not deduce template argument for 'S'
Beside changing the compiler, is there a workaround I can use to get the array's size?

This could be a limitation of VC6, have you tried other compilers?

but I've got this message:
error C2265: '' : reference to a zero-sized array is illegal
Arrays with zero size are illegal in C++.
So this probably means you tried with an array of zero size.
this compiles, but when I try to use it:
If you don't use it. Then the compiler is going to ignore a template (even if it has errors). This is because you can not always deduce if a template function is correct without knowing the types involved. So unless there is a call to a template function no error message will be generated.
template <typename T,unsigned S>
unsigned getArraySize(const T v[S]) { return S; }
This fails because you are not allowed to pass arrays as parameters (you can only pass references to arrays).

Related

Template Alias, Variable Template, and auto type deduction failing to deduce template argument

While working on my class declaration I'm having some confusion on how to use alias templates and template variables within in a non class template while trying to use auto type deduction.
Signal.h
#ifndef SIGNAL_H
#define SIGNAL_H
#include <cstdint>
template<typename T>
using TimeSignal = T;
using DiscreteTime = TimeSignal<std::uint8_t>;
using ContinuousTime = TimeSignal<double>;
class Signal {
private:
template<typename T>
static TimeSignal<T> time_;
double voltage_;
double current_;
public:
template<typename T>
explicit Signal( TimeSignal<T> time, double voltage = 0, double current = 0 ) :
voltage_{voltage}, current_{current}
{ time_ = time; }
double sampleVoltage() { return voltage_; }
double sampleCurrent() { return current_; }
template<typename T>
static auto atTime() { return time_; }
};
#endif // SIGNAL_H
And I would be using it like this:
#include <iostream>
#include "Signal.h"
int main() {
DiscreteTime t1{ 5 };
ContinuousTime t2{ 7.5 };
Signal s1{ t1, 3.5, 0.05 );
Signal s2{ t2, 4.3, 0.09 );
auto time1 = s1.atTime();
auto time2 = s2.atTime();
return 0;
}
I don't want to template this class, so I was thinking about having an internal variable template. Outside of the class I was trying to use a template alias to have the different "TimeSignals" be descriptive as a "DiscreteTime" is typically and integral type and a ContinousTime is a floating point or over the set of Real numbers. I was however templating the constructor of this class that takes in the TimeSignal type and wanted the class to deduce the or to auto resolve it's internal variable template to that type depending which of the two types were passed in. Finally I was trying to use auto type deduction to return that type.
I don't know if its the syntax or the usage but this has me stumped. I'm not sure how to get this to a working compile state.
This is the current compiler errors that Visual Studio 2017 is giving me.
1>------ Build started: Project: Circuit Maker Simulator, Configuration: Debug x64 ------
1>main.cpp
1>c:\...\main.cpp(15): error C2672: 'Signal::atTime': no matching overloaded function found
1>c:\...\main.cpp(15): error C2783: 'auto Signal::atTime(void)': could not deduce template argument for 'T'
1>c:\...\Signal.h(64): note: see declaration of 'Signal::atTime'
1>c:\...\main.cpp(24): error C2672: 'Signal::atTime': no matching overloaded function found
1>c:\...\main.cpp(24): error C2783: 'auto Signal::atTime(void)': could not deduce template argument for 'T'
1>c:\...\Signal.h(64): note: see declaration of 'Signal::atTime'
1>Done building project "Circuit Maker Simulator.vcxproj" -- FAILED.
The compiler error's obvious to what they are saying, but it's like they are screaming or yelling at me without any help, assistance or suggestions on how to fix or resolve this...
Edit
User rafix07 helped me quite a bit with his answer and it was helpful. I was missing a couple of things, two of them I may have eventually caught onto if I kept staring at it long enough and that was the use of the variable templates within the class needing it's template argument or parameter. The other was using the scope resolution operator in the main function to call the static function. I could of found them given some time.
The one issue that had me stumbling in circles was the fact that I had to explicitly instantiate the function template of the type I want when calling it. This is the one that would of had me pulling out my hair for ours...
After adjusting the code according to the link in his answer I'm now able to compile, however I am now getting linker errors for unresolved external symbols and it has to do with the template variables. Which shouldn't be a problem, just need to define it within a cpp file to resolve static variables.
First of all, atTime is static method so only way to call it is to use scope resolution operator ::. atTime takes no arguments, so T cannot be deduced, and you need to put type in template arguments list explicitly:
auto time1 = Signal::atTime<DiscreteTime>();
auto time2 = Signal::atTime<ContinuousTime>();
In ctor of Signal and atTime function you have to specify T for which variable template is accessed:
template<typename T>
explicit Signal( TimeSignal<T> time, double voltage = 0, double current = 0 ) :
voltage_{voltage}, current_{current}
{ time_<T> = time; }
Full working code is here.

Dispatch template <auto>

I try to dispatch between two functions using if constexpr. The dispatcher function should accept for example std::size_t and an arbitrary class type.
It works if I just call it with a scalar type, but if I try to pass a class type it triggers a compile error which is not really helpful to me (please see below).
Please have a look at my current approach:
template <auto Other>
constexpr auto mul() const {
if constexpr (std::is_scalar_v<decltype(Other)>)
return mul_with_scalar<Other>();
else
return mul_with_matrix<Other>();
}
template <size_t Scalar>
constexpr auto mul_with_scalar() const {
return apply([](size_t v, auto) { return v * Scalar; },
std::make_index_sequence<Size>{});
}
template <class Other>
constexpr auto mul_with_matrix() const {
return size_t{0}; // implement me
}
note: candidate: template<auto Other> constexpr auto matrix<Rows, Cols, Vals>::mul() const [with auto Other = Other; long unsigned int Rows = 3; long unsigned int Cols = 3; long unsigned int ...Vals = {}]
constexpr auto mul() const {
^~~
./constexpresian/matrix.hpp:81:18: note: template argument deduction/substitution failed:
I wan't that the function mul can handle non-type and type parameters.
That is not possible in C++. A template parameter can be a type or a value (or a template), but it cannot be both. template<auto Name> makes Name a value template parameter, the type of whose value will be deduced at the time the value is passed.
But since it is a compile-time value, you can wrap its value in a type. For integer types, std::integer_constant will work. For future C++ revisions that allow other kinds of value parameters, you'll have to use a more generic wrapper.
There is one question I have, you can refer to my comment below your post that pertains to the term Size.
I tried your code above as is even with Size the way it is to see the compiler errors and this is coming from Visual Studio 2017 v4.6.0105 c++17 on Win 7 x64 Home Premium under x86 Debug on an Intel Quad Core Extreme.
1>------ Build started: Project: StackOverflow, Configuration: Debug Win32 ------
1>Learner.cpp
1>c:\users\skilz80\documents\visual studio 2017\projects\stackoverflow\stackoverflow\learner.h(75): error C3533: a parameter cannot have a type that contains 'auto'
1>c:\users\skilz80\documents\visual studio 2017\projects\stackoverflow\stackoverflow\learner.h(75): error C2270: 'mul': modifiers not allowed on nonmember functions
1>c:\users\skilz80\documents\visual studio 2017\projects\stackoverflow\stackoverflow\learner.h(83): error C2270: 'mul_with_scalar': modifiers not allowed on nonmember functions
1>c:\users\skilz80\documents\visual studio 2017\projects\stackoverflow\stackoverflow\learner.h(89): error C2270: 'mul_with_matrix': modifiers not allowed on nonmember functions
1>Done building project "StackOverflow.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Maybe this interpretation of these compiler errors might help you.
Here are some links that might help concerning auto and template parameters:
StackOverflow : Advantages of auto in template parameters in C++17
open-std.org : Declaring non-type template arguments with auto
www.bfilipek.com : C++17 in details: Templates

MSVC error with constexpr array as template non-type parameter

I'm trying to understand if what I'm seeing is an MSVC compiler bug or a misunderstanding on my part. I'm trying to use a simple compile-time string literal template parameter, like so:
constexpr const char teststr[] = "teststr";
template <const char *N>
struct Test {
static constexpr const char *name = N;
};
using TEST = Test<teststr>;
However, MSVC reports that the teststr parameter is not a compile-time expression: error C2975: 'Test': invalid template argument for 'N', expected compile-time constant expression (on the using TEST line).
Is this my mistake, or a compiler bug? I am using Visual Studio 2017 version 15.1.
It is a compiler bug.
In addition, it is a C++11 feature to permit addresses of objects with internal linkage in template arguments, not C++14.
Is it important that name is static ?
This compiles with MSVC 2015:
char teststr[] = "teststr";
template <const char *N>
struct Test
{
const char *name = N;
};
using TEST = Test<teststr>;

Why can the simplest C++ code not be compiled?

template<class CharType>
struct MyString
{
MyString()
{}
MyString(CharType*)
{}
};
int main()
{
char* narrow_str = 0;
MyString<char>(narrow_str); // error C2040
}
My compiler is VC++ 2013 RC.
The simplest code cannot be compiled because of the error C2040.
error C2040: 'narrow_str' : 'MyString' differs in levels of
indirection from 'char *'
Why?
The problem is this is actually not being parsed as a constructor call but as a variable definition. The problem is you already defined a variable narrow_str. You may have already known this but you can easily fix this by giving it a name.
template<class CharType>
struct MyString
{
MyString()
{}
MyString(CharType*)
{}
};
int main()
{
char* narrow_str = 0;
MyString<char> ns(narrow_str); // error C2040
}
BTW this is also the source of the most vexing parse which occurs when this type of syntax is used in a function argument.
To be honest though I'm surprised that you got a different error because both g++ and clang gave me a clear error.
your syntax in creating a struct is wrong .
change
MyString<char>(narrow_str); // error C2040
to
MyString<char> myString(narrow_str);
will be ok.

Unable to compile nsgmls with template erros

I am a avid emacs user, and want to use sgml markup check routine.
I was naturally headed towards nsgmls, and downloded the source code to compile it.
However, there was a strange error coming from the compiler with the followings.
./../include/RangeMap.h:57: error: type ‘Vector<RangeMapRange<From, To> >’ is not deri ved from type ‘RangeMapIter<From, To>’
./../include/RangeMap.h:57: error: expected ‘;’ before ‘ptr_’
./../include/RangeMap.h: In member function ‘Boolean RangeMapIter<From, To>::next(From&, From&, To&)’:
./../include/RangeMap.h:47: error: ‘ptr_’ was not declared in this scope
I know that some times compiler gets disgruntled by template and typename madness, however the codes seems to have already used typename correctly within the code.
Here are the cope snippets that arouses these errors.
template<class From, class To>
class RangeMapIter {
public:
RangeMapIter(const RangeMap<From,To> &map);
Boolean next(From &fromMin, From &fromMax, To &toMin) {
if (!count_)
return 0;
else {
fromMin = ptr_->fromMin;
fromMax = ptr_->fromMax;
toMin = ptr_->toMin;
ptr_++;
count_--;
return 1;
}
}
private:
size_t count_;
typename Vector<RangeMapRange<From,To> >::const_iterator ptr_;
};
Can anybody help me hash out those errors?
This error message is given by GCC in the wrong order of both type names. (but it apparently fixed this in the latest version). It is meant to say that Vector<RangeMapRange<From,To> >::const_iterator was not found to be a type name. The underlying cause of this diagnostic is that the code is parsed as an access-declaration, which has the following syntax
::[opt] nested-name-specifier template[opt] unqualified-id ;
An example of that syntax
struct A {
int a;
};
struct B : A {
// equivalent to: using A::a;
A::a;
};
In C++11 this access-declaration construct was taken out of the specification and it was deprecated in C++03. But since the compiler still supports parsing it, when the Vector<RangeMapRange<From,To> >::const_iterator is not found to be a type, it will be taken as a name to be declared in an access-declaration (so the parser moves forward across the type specifier section). Hence according to the above syntax, after the unqualified-id which in this case is const_iterator (and in my example was a), it wants to see a semicolon and it wants that Vector<RangeMapRange<From, To> > is a base class of RangeMapIter<From, To>, but confusingly the diagnostic it gives has it the other way around.
Check your names and make sure the type exists.