Couldn't deduce template parameter for Eigen::Matrix - c++

When I try to compile the following function (forward) using MSVC 19.latest I get the following error message.
'Eigen::Matrix<float,ann_output_len<LayerNodeConfig...>::value,1,0,_Rows,1> forward(const
ArtificialNeuralNetwork<InputSize,LayerNodeConfig...> &,const Eigen::Matrix<float,Rows,1,0,_Rows,1> &)':
could not deduce template argument for 'const Eigen::Matrix<float,Rows,1,0,_Rows,1> &' from
'Eigen::Matrix<float,2,1,0,2,1>'
forward interface
template<int InputSize, int ... LayerNodeConfig>
auto forward(const ArtificialNeuralNetwork<InputSize, LayerNodeConfig...>& ann,
const RL::Arrayf<InputSize>& input)
-> typename ANN::output_t<LayerNodeConfig...>
In main function
RL::Arrayf<2> X;
auto Y = forward(sampling_policy, X);
Now what I don't understand is why can't the compiler substitute Rows and _Rows with 2.
Any insight is appreciated.
You can try the full code in godbolt.org using this link, https://godbolt.org/z/7Mj5ee and try to compile it yourself if you like.
Note: I tried to compile the same code with latest GCC compiler and it compiled.
Update - Mar 06, 2021:
I made a workaround by changing the interface of function forward to accept Eigen::DenseBase<Derived> instead of RL::Arrayf<InputSize>.
Anyone who is interested can read more about it here, https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html

Related

Why do I get "error: reference to 'align_val_t' is ambiguous" with Intel's C++ 2022 compiler when using std::inplace_merge?

When I try to compile this with the Intel C++ Compiler 2022 toolset for Visual Studio 2022:
#include <algorithm>
int main()
{
int x = 0;
std::inplace_merge(&x, &x, &x);
}
I get:
VC\Tools\MSVC\14.34.31933\include\xmemory(1429,48): error : reference to 'align_val_t' is ambiguous
_Pbuf = ::operator new (_Size, align_val_t{alignof(_Ty)}, nothrow);
^
VC\Tools\MSVC\14.34.31933\include\algorithm(7152,57): note: in instantiation of function template specialization 'std::_Optimistic_temporary_buffer<int>::_Optimistic_temporary_buffer<long long>' requested here
_Optimistic_temporary_buffer<_Iter_value_t<_BidIt>> _Temp_buf{(_STD min)(_Count1, _Count2)};
^
VC\Tools\MSVC\14.34.31933\include\algorithm(7160,10): note: in instantiation of function template specialization 'std::inplace_merge<int *, std::less<>>' requested here
_STD inplace_merge(_First, _Mid, _Last, less<>{});
^
Temp.cpp(6,7): note: in instantiation of function template specialization 'std::inplace_merge<int *>' requested here
std::inplace_merge(&x, &x, &x);
^
VC\14.34.31933\include\vcruntime_new.h(27,16): note: candidate found by name lookup is 'std::align_val_t'
enum class align_val_t : size_t {};
^
note: candidate found by name lookup is 'std::align_val_t'
I tried digging through the STL sources, but I can't find where the ambiguity is.
Why does this error occur? And how do I get around it?
Answering my own question, but it seems to be a bug with precompiled headers. This occurs even if the precompiled header files are empty.
Avoiding precompiled headers seems to avoid the issue.
If anyone has a better workaround or more details, please do post it.

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

Function template overload resolution fails in Visual C++ 2017

I am trying to figure out if what I wrote is legal C++14 w.r.t. unambiguous function template overload resolution.
In my opinion, the below program should compile and return 3.
Various versions of Clang and GCC compute just that at compile time (using -std=c++14 -O2), but Visual C++ 2017 (Version 15.5.2; latest update at time of writing) chokes on it with the below error message.
enum class Enum0 { State };
enum class Enum1 { State };
template <Enum0 Param0 = Enum0::State>
int get()
{
return 1;
}
template <Enum1 Param1>
int get()
{
return 2;
}
int main()
{
int sum = 0;
sum += get(); // should call instantiation of first function template
sum += get<Enum1::State>(); // should call instantiation of second function template
return sum;
}
This is the emitted error message by the Visual C++ compiler:
20 : <source>(20): error C2668: 'get': ambiguous call to overloaded function
11 : <source>(11): note: could be 'int get<Enum1::State>(void)'
5 : <source>(5): note: or 'int get<Enum0::State>(void)'
20 : <source>(20): note: while trying to match the argument list '()'
See https://godbolt.org/g/PhH2VY for a live demonstration (and https://godbolt.org/g/BVEv79 for the previous code example before editing the question).
Change the compiler to MVSC to see the compilation failing. GCC and Clang do not indicate any issue. Both nicely emit the following x86 assembly:
mov eax, 3
ret
Are GCC and Clang too lenient, or is this an issue with Visual C++?
That's a good question, isn't it. If I change the second call to get with:
sum += get<Enum1::State, int>(0.0); // should call instantiation of second function template
... then it compiles...
Notice, I add a second template argument. In my day to day work, I use an old dialect of C++ compatible with MFC...so take my reasoning with a grain of salt. But, since you are only providing one argument to the template, and the second template requires two arguments, ISTM that the VC++ compiler is trying to use the first template because it has default arguments and can take only one argument. So it chooses that template but cannot do the conversion from Enum1 to Enum0.

ensure that an iterator dereferences to a certain type

I have to implement a function that takes an iterator. The iterator must dereference to a certain type, say int:
template<typename iter>
void f(iter i) {
// do something here ...
int t = *i;
// do something here ...
}
The problem with this code is that if a user calls the function like this
vector<string> v;
v.push_back("aaa");
f(v.begin());
he will see an error pointing to some place in my code, not in his code (which will be confusing to him). I want the error to be in user's code to ease debugging.
GMan already pointed to a method to solve this via compile time assertions. There is another way to do this, which I prefer (it's my favorite C++ technique). You can put constraints on function arguments in a way that the function is ignored for overload resolution if the constraints don't fit. This is quite terrific, because you can fine tune your function overloads to arbitrary conditions. Here's how:
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
#include <vector>
template<typename Iter> typename
boost::enable_if<
boost::is_same<typename Iter::value_type,int>,
void>::type
foo(Iter it) { }
int main() {
std::vector<int> v; // this is OK
foo(v.begin());
std::vector<double> v2; // this is an error
foo(v2.begin()); }
If you compile this, you will get
b.cc: In function 'int main()':
b.cc:19:16: error: no matching function for call to 'foo(std::vector<double>::iterator)'
This is because the compiler would consider foo() only, if it's argument has a value_type type inside, which is 'int' (This is what the enable_if part means). The second call of foo() can't satisfy this constraint.
enable_if is mentioned a couple of times in SO, just search for it: https://stackoverflow.com/search?q=enable_if
You could do something like this:
#include <boost/type_traits/is_convertible.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/mpl/assert.hpp>
template <typename Iter>
void foo(Iter pIter)
{
BOOST_MPL_ASSERT_MSG(
(boost::is_convertible<BOOST_TYPEOF(*pIter), int>::value),
DEREFERENCED_ITERATOR_MUST_BE_CONVERTIBLE_TO_INT,
(int));
// ...
}
#include <vector>
#include <string>
int main(void)
{
std::vector<std::string> v(5);
foo(v.begin());
}
Which makes the message quite visible:
error C2664: 'boost::mpl::assertion_failed' : cannot convert parameter 1 from 'boost::mpl::failed ************(__thiscall foo::DEREFERENCED_ITERATOR_MUST_BE_CONVERTIBLE_TO_INT::* ***********)(int)' to 'boost::mpl::assert::type'
But like James says, most compilers give plenty of information to find out what happened anyway.
Given the code in question, most compilers will refer to the point of instantiation in the diagnostic message. For the following, line 16 is the line f(v.begin());.
Microsoft Visual C++ reports:
> c:\example\main.cpp(16) : see reference to function template instantiation 'void f<std::_Vector_iterator<_Myvec>>(iter)' being compiled
1> with
1> [
1> _Myvec=std::_Vector_val<std::string,std::allocator<std::string>>,
1> iter=std::_Vector_iterator<std::_Vector_val<std::string,std::allocator<std::string>>>
1> ]
g++ reports:
main.cpp:16: instantiated from here
Intel C++ Compiler and Comeau both report:
detected during instantiation of
"void f(iter) [with iter=std::string *]" at line 16
You need to set a constraint on the generic type.