template template argument in C++ - c++

#include <vector>
#include <iostream>
#include <string>
using namespace std;
#include <vector>
#include <iostream>
#include <string>
using namespace std;
// Template-template argument must
// be a class; cannot use typename:
template<typename T, template<typename> class C>
void print2(C<T>& c) {
copy(c.begin(), c.end(),
ostream_iterator<T>(cout, " "));
cout << endl;
}
int main() {
vector<string> v(5, "Yow!");
print2(v);
} ///:~
This code looks perfect right to me. But this snippet can't compile in My Mac. The error information is the following
note: candidate template ignored: substitution failure [with T = std::__1::basic_string<char>]: template template argument has
different template parameters than its corresponding template template parameter
void print2(C<T>& c) {
^
1 error generated.

This is because std::vector is not a single-argument template. Standard mandates an element type and allocator type arguments for std::vector.
If you are not on legacy C++ and can use variadic templates, you can declare your function like this:
template<typename T, template<typename...> class C>
void print2(C<T>& c);

Related

Why c++ don't infer template argument T for simple nested types variables? [duplicate]

This question already has answers here:
Class template argument deduction not working with alias template
(2 answers)
Closed 7 months ago.
In this piece of code:
#include <iostream>
#include <vector>
#include <utility>
template <typename T>
using Separation = std::pair<std::vector<T>, std::vector<T>>;
int main()
{
std::vector<int> vector1 = {1};
Separation s1(vector1, vector1);
std::cout << s1.first[0];
return 0;
}
The g++ compiler says: error: missing template arguments before ‘(’ token
That can be fixed just by adding the template parameter to Separation. But, if v1 is a vector of integer, shouldn't the compiler be able to understand that T should be generic that comes from the vector??
If you can make it a subtype, you may add a deduction guide:
#include <iostream>
#include <vector>
#include <utility>
template <typename T>
struct Separation : std::pair<std::vector<T>, std::vector<T>> {
using std::pair<std::vector<T>, std::vector<T>>::pair;
};
template <class T>
Separation(std::vector<T>, std::vector<T>) -> Separation<T>;
int main()
{
std::vector<int> vector1 = {1};
Separation s1(vector1, vector1); // works fine
std::cout << s1.first[0];
return 0;
}

Is there a way to define a template member in a non-template class? #2

I have a template class class_A:
// class_A.h
#pragma once
#include <iostream>
#include <tuple>
template <class T>
class class_A
{
public:
class_A(){}
T Function_A(T parameter)
{
return parameter;
}
};
that I am trying to use in a non-template class class_B as private member:
// class_B.h
#pragma once
#include <tuple>
#include <iostream>
#include "class_A.h"
class class_B
{
public:
class_B();
template <typename T> T Evaluate(T parameter);
private:
std::tuple<class_A<double>, class_A<char> > As;
};
and
// class_B.cc
#include "class_B.h"
class_B::class_B(){}
template <typename T>
T class_B::Evaluate(T parameter)
{
return std::get<class_A<T>>(As).Function_A(parameter); //This is causing error
//return parameter // This works
}
template double class_B::Evaluate(double parameter);
template char class_B::Evaluate(char parameter);
and my main.cc is:
// main.cc
#include<iostream>
#include <string>
#include "class_B.h"
using namespace std;
int main()
{
class_B B;
std::cout<< B.Evaluate(5.2) <<std::endl;
std::cout << B.Evaluate('h') << std::endl;
return 0;
}
I get the following error:
src/class_B.cc:8:12: error: no matching function for call to 'get'
return std::get<class_A<T>>(As).Evaluate(parameter);
.
.
.
etc.
This is a trial of the answer: https://stackoverflow.com/a/55357742/9203360 that didn't work, but would be ideal if it did.
As I mentioned in the comments, the overload of std::get taking a type as template argument and returning the tuple element of that type is available only since C++14.
Per your comment you were not compiling against C++14 or later and so there was no match for std::get with a type as first template argument.
The
std::get< class_A< T>>(As)
get an instance of class_A, so you can't call the Evaluate Method, doesn't exist. You should call method Function_A, or define Evaluate method in class_A
return std::get<class_A<T>>(As).Function_A(parameter); // Call Function_A
It works in Visual Studio 2015 - Windows Platform 10.0.17763.0
Plus you need c++14 for std::get to work.

Check if type can be an argument to boost::lexical_cast<string>

I have the following traits class(IsLexCastable) to check if a type can be converted to a string by calling boost::lexical_cast<string>. It erroneously returns true for vector<int>.
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
namespace std
{
/// Adding to std since these are going to be part of it in C++14.
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
}
template <typename T, typename = void>
struct IsLexCastable : std::false_type
{
};
template <typename T>
struct IsLexCastable<T, std::enable_if_t<std::is_same<std::string, decltype(boost::lexical_cast<std::string>(std::declval<T>()))>::value> > : std::true_type
{
};
int main()
{
vector<int> a = {1, 2, 3};
// cout << lexical_cast<string>(a) << endl;
cout << IsLexCastable<decltype(a)>::value << endl;
return 0;
}
This program prints 1, but lexical_cast<string>(a) results in a compile error. What is the right way to implement IsLexCastable?
(This was compiled with g++48 -std=c++11, and boost 1.55.0.)
Your expression is not sufficient, as the lexical_cast function template takes everything and only reports errors via an internal static_assert. Instead test whether inserting the object into an std::ostream is valid:
template <typename T, typename=void>
struct IsLexCastable : std::false_type {};
// Can be extended to consider std::wostream as well for completeness
template <typename T>
struct IsLexCastable<T,
decltype(void(std::declval<std::ostream&>() << std::declval<T>()))>
: std::true_type {};
Demo.
That requirement is called OutputStreamable by the documentation, and the direct one imposed onto the source type.
Why did your implementation not work?
decltype only causes the instantiation of the declaration of a function template. The internal static assertion is triggered inside the definition of lexical_cast though, hence it cannot be used in SFINAE.
[temp.inst]/10:
If a function template or a member function template specialization
is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated (14.8.3).
The answer by Columbo answers the question, but I had problems adapting to to an input stream. My use case was that I wanted to call lexical_cast to convert from string to T. Boost offers has_right_shift and has_left_shift, which worked and should allow more flexibility for similar constructs.
template <typename T, typename=void>
struct IsLexCastable : std::false_type {};
template <typename T>
struct IsLexCastable<T,
typename std::enable_if<boost::has_right_shift<T>::value>::type>
: std::true_type {};

What does it mean when c++ template definition comes with =

I'm trying to teach myself generic classes and functions declaration and Boost library at the sometime.
I've encountered an example and don't really understand what typename f=... means.
Could you help me to understand the concept of using template declaration with = sign in cases like: template <typename T, typename F=ublas::row_major>? Here is the full program that I'm trying to understand.
#include <algorithm>
#include <vector>
#include <boost/numeric/ublas/storage.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
namespace ublas = boost::numeric::ublas;
template <typename T, typename F=ublas::row_major>
ublas::matrix<T, F> makeMatrix(std::size_t m, std::size_t n, const std::vector<T> & v)
{
if(m*n!=v.size()) {
; // Handle this case
}
ublas::unbounded_array<T> storage(m*n);
std::copy(v.begin(), v.end(), storage.begin());
return ublas::matrix<T>(m, n, storage);
}
It is Default Argument that you are passing to Template.
e.g
Template<typename T, int N = 17>
class Generic
{
}
here, second Argument is default value
in youe case F=ublas::row_major is default value.
for deep understanding http://en.cppreference.com/w/cpp/language/template_parameters
It's a default value/type for the entry parameter of that template-d function. It's like compiler write down ublas::row_major everywhere you've written F, when you call makeMatrix without second template argument.
makeMatrix<int, int>( ... // Second parameter is `int`
makeMatrix<int> ( ... // Second is specified by default to `ublas::row_major`
To read more..
It is a default argument, which is used when nothing else is specified.

Boost mpl for each and free functions

Why this code does not compile:
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <iostream>
using namespace std;
using namespace boost;
template <class T> // specific visitor for type printing
static void print_type(T t)
{
std::cout << typeid(T).name() << std::endl;
}
typedef mpl::vector<int, long, char*> s;
int main ()
{
mpl::for_each<s>(print_type());
}
I wonder - how to make boost mpl for_each work with free functions from same class?
As stated you need a functor.
The code below includes an additional wrap template that allows the print functor to cope with references.
#include <iostream>
#include <typeinfo>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/placeholders.hpp>
using namespace std;
using namespace boost;
template <typename T>
struct wrap {};
struct print_type
{
template< typename T>
void operator()( wrap<T> ) const
{
cout << typeid(T).name() << "\n";
}
};
typedef mpl::vector<int, long&, char*> s;
int main ()
{
mpl::for_each<s, wrap<mpl::placeholders::_1> >(print_type());
return 0;
}
Note: this code based on examples in the book 'C++ Template Metaprogramming by David Abrahams and Aleksy Gurtovoy
mpl::for_each<s>(print_type());
This is wrong in a couple of ways.
First, print_type is a function that returns void. print_type() is an attempt to call that function. Since it returns nothing, you can't stick its non-existent return value into something else.
Second, print_type is a template function. You cannot call a template function without specifying the template parameters. So print_type() is ill-formed.
Third, even mpl::for_each<s>(print_type) doesn't work, because print_type is not a value (nor is it convertible to a value); it is a template. You cannot pass a template as the argument of a function. That's why visitors (for many things, not just MPL) are objects, which can have template operator() members.