I have a function template printSize calling the overloaded function getSize before getSize is declared. For a clearer structure of my program, I would like to put both functions in different namespaces A and B, as the commented code lines show. However, ADL will then fail to find getSize.
Actually, printSize and getSize are implemented in different header files. Therefore, I cannot put a using namespace directive.
#include <array>
#include <iostream>
#include <string>
namespace A {
template <typename T> struct tag {};
template <typename T>
void printSize(const T &data)
{
size_t data_size = getSize(data, tag<T>{});
//size_t data_size = B::getSize(data, tag<T>{});
std::cout << "Size: " << data_size << std::endl;
}
//} // namespace A
//namespace B {
constexpr size_t getSize(const int &, tag<int>)
{
return sizeof(int);
}
size_t getSize(const std::string &str, tag<std::string>)
{
return str.size();
}
template <typename T, size_t N>
size_t getSize(const std::array<T, N> &array, tag<std::array<T, N>>)
{
size_t array_size = 0;
for (const T &element : array)
array_size += getSize(element, tag<T>{});
return array_size;
}
} // namespace A/B
int main()
{
int a;
A::printSize(a);
std::array<std::string, 2> arr = {{"foo", "foobar"}};
A::printSize(arr);
return 0;
}
Is there a way to make this code compile with printSize and getSize being defined in different namespaces?
One solution would be to put the tag into the B namespace, and pull it into A.
namespace B {
template <typename T> struct tag {};
}
namespace A {
using B::tag;
}
Now, because tag comes from the B namespace, it will associate B for ADL.
You can use a using declaration to introduce a name from another namespace. For example:
template <typename T>
void printSize(const T &data)
{
using B::getSize;
std::size_t data_size = getSize(data, tag<T>{});
std::cout << "Size: " << data_size << std::endl;
}
getSize depends on a template parameter T, so ADL will be used in the second phase of lookup (when this template is instantiated) to find other getSizes provided by the user. Here B::getSize should be declared before printSize and tag itself seems to be redundant.
Related
I'd like to supply two forms of a GetLength(psz) style function - one that doesn't know an upper bounds, and one that does:
template <typename T>
size_t GetLength(const T * psz) { /* compute size w/o knowing what upper bound may be */ }
template <typename T, size_t size>
size_t GetLength(const T(&psz)[size]) { /* we know the upper bound */ }
I'd like that this not be ambiguous. I want the array-sized version to be chosen when the argument is an array of known size. I want the unbounded version chosen when the argument is just a pointer, not a known fixed array.
I'd also offer a 3rd version which explicitly takes the upper bounds as an argument, without templated size deduction, for passing that info in from an outer context which has otherwise lost the ability to deduce that from its local arguments.
Is there a technique I can use to force the compiler to discount the 1st version of my function (no known bounds) when the bounds is known?
Is there a technique I can use to force the compiler to discount the 1st version of my function (no known bounds) when the bounds is known?
What about adding a level of indirection?
template <typename T>
std::size_t GetLength (const T * psz, int)
{ /* compute size w/o knowing what upper bound may be */ }
template <typename T, size_t size>
std::size_t GetLength (const T(&psz)[size], long)
{ /* we know the upper bound */ }
template <typename T>
std::size_t GetLength (T const & t)
{ GetLength(t, 0L); }
Adding an unused different parameter (int or long) you can select the preferred version.
We could use type traits:
#include <type_traits>
// If T is an array
template<
typename T,
typename std::enable_if <
std::is_array<T>{},
size_t
> ::type Extent = std::extent<T>::value
>
size_t GetLength(const T& t)
{
return Extent;
}
// If T is not an array
template<typename T,
typename std::enable_if <
!std::is_array<T>{},
size_t
> ::type = 0
>
size_t GetLength(const T& t)
{
return {};
}
int main()
{
int arr[5]{};
GetLength(arr); // calls first
//decay to pointer
auto val = arr;
GetLength(val); // calls second
}
If you have access to a recent version of boost, you can use the incredibly powerful HOF library (stands for higher order functions).
One of the functions I use most to simplify code path selection based on argument type is the function first_of.
The way this works is that you give it a list of template function objects (or lambdas) in the order you want the compiler to try them. The first legal function object in the list is selected.
example:
#include <cstddef>
#include <boost/hof.hpp>
#include <cstring>
#include <utility>
#include <iostream>
// a function to compute length from a pointer. For exposition,
// I have only considered char pointers but any number of overloads will work.
template<class T>
std::size_t
string_pointer_length(T*p)
{
// for exposition
return std::strlen(p);
}
// a function to compute string length from a literal
template<class T, std::size_t N>
constexpr
std::size_t literal_string_length(T (&s)[N])
{
return N - 1;
}
// The generic GetLength function which takes any kind of string
template <typename T>
std::size_t GetLength(T&& str)
{
// select the FIRST legal choice of the following lambdas and invoke...
return boost::hof::first_of(
[](auto&&s) BOOST_HOF_RETURNS(literal_string_length(s)),
[](auto&&s) BOOST_HOF_RETURNS(string_pointer_length(s))
)(str);
}
int main()
{
static const auto lit = "hello";
auto plit = std::addressof(lit[0]);
auto n = GetLength(lit);
auto n2 = GetLength(plit);
std::cout << n << ", " << n2 << std::endl;
}
The macro BOOST_HOF_RETURNS saves us having to spell out the lambdas like this:
return boost::hof::first_of(
[](auto&&s) -> decltype(literal_string_length(s)) { return literal_string_length(s); },
[](auto&&s) BOOST_HOF_RETURNS(string_pointer_length(s))
)(str);
If you're not able to use boost.hof, writing our own replacement is surprisingly trivial:
#include <cstddef>
#include <cstring>
#include <tuple>
#include <utility>
#include <iostream>
template<class T>
std::size_t
string_pointer_length(T*p)
{
// for exposition
return std::strlen(p);
}
template<class T, std::size_t N>
constexpr
std::size_t literal_string_length(T (&s)[N])
{
return N - 1;
}
template<class...Args, class This, class...Others>
constexpr auto try_these(std::tuple<Args...> args, This _this, Others...others)
{
if constexpr (std::is_invocable_v<This, Args...>)
{
return std::apply(_this, args);
}
else
{
return try_these(args, others...);
}
}
struct invoke_string_pointer_length
{
template<class S>
constexpr auto operator()(S&& s) const -> decltype(string_pointer_length(s))
{ return string_pointer_length(s); }
};
struct invoke_literal_string_length
{
template<class S>
constexpr auto operator()(S&& s) const -> decltype(literal_string_length(s))
{ return literal_string_length(s); }
};
template <typename T>
std::size_t GetLength(T&& str)
{
return try_these(std::forward_as_tuple(std::forward<T>(str)),
invoke_literal_string_length(),
invoke_string_pointer_length());
}
int main()
{
static const auto lit = "hello";
auto plit = std::addressof(lit[0]);
auto n = GetLength(lit);
auto n2 = GetLength(plit);
std::cout << n << ", " << n2 << std::endl;
}
I'm trying to specialize hash to include std::vector for all arithmetic types, but it's throwing a few errors
./includes/helpers.hpp:14:22: error: default template argument in a class template partial specialization
typename = std::enable_if_t<std::is_arithmetic<dtype>::value> >
^
./includes/helpers.hpp:16:8: error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct hash<std::vector<dtype> >
^~~~~~~~~~~~~~~~~~~~~~~~~
I tried to follow as close as I could with different enable_if_t guides. But it doesn't seem to be working, what am I doing wrong?
It seems to work without using enable_if_t. But then there would be a possible conflict with vectors that shouldn't use this hash
This is my code so far (editted to be more "complete")
#include <iostream>
#include <type_traits>
#include <vector>
namespace std {
template <typename dtype,
typename = std::enable_if_t< std::is_arithmetic<dtype>::value> >
struct hash<std::vector<dtype> > {
size_t operator()(const std::vector<dtype> &input)
{
//perform hash
}
};
}
using namespace std;
int main()
{
const vector<int> i{1,2,3,4};
cout << hash<vector<int>>()(i) << endl;
return 0;
}
The problem is, that std::hash has only a single template parameter and you cannot add an additional defaulted template parameter in a partial specialization. So you have several choices, depending on what you want to do with your hash.
Please also rethink your approach. This comment by Yakk is very useful:
You may not specialize templates in std unless the specialization depends on a user-provided type. – Yakk
You can easily fix thisby not putting your own hash into the std namespace.
You could simply remove the enable_if from the template argument list and replace it with a
static_assert(std::is_arithmetic<dtype>::value, "!");
in the struct body, given that you only ever want to hash vectors of arithmetic type.
SFINAE on the call operator. This way, you have to provide all the hash methods for all other vector types within the same struct. Also you have to go through some funny business of repeating the template parameter to make the compiler happy. It's very important that your SFINAE criteria are mutually exclusive, otherwise you'll get horrible errors.
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
namespace std {
template< typename dtype >
struct hash< std::vector<dtype> >
{
template< typename T = dtype >
std::enable_if_t<std::is_arithmetic<T>::value, size_t>
operator()(const std::vector<T> &input) const
{
constexpr size_t FNV_prime = 1099511628211ul;
constexpr size_t FNV_offset = 14695981039346656037ul;
size_t hashed = FNV_offset;
for(const auto &n:input)
{
hashed ^= n;
hashed *= FNV_prime;
}
return hashed;
}
template< typename T = dtype >
std::enable_if_t<!std::is_arithmetic<T>::value, size_t>
operator()(const std::vector<T> &input) const
{
std::cout << "No hash for you :-(\n";
return 0;
}
};
} // namespace std
int main() {
{
std::vector<int> v{1,2,3,4};
size_t hash = std::hash<std::vector<int>>{}(v);
std::cout << hash << "\n";
}
{
std::vector<std::string> v{"Hello", "world!"};
size_t hash = std::hash<std::vector<std::string>>{}(v);
std::cout << hash << "\n";
}
}
Live example
You can also declare your own struct for hashing and add as many template parameters as you want. Then you just need std::hash to inherit from your custom struct.
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
template < typename T, bool = std::is_arithmetic<T>::value >
struct vector_hash;
template < typename T>
struct vector_hash<T,true> {
size_t operator()(std::vector<T> const &input) const
{
constexpr size_t FNV_prime = 1099511628211ul;
constexpr size_t FNV_offset = 14695981039346656037ul;
size_t hashed = FNV_offset;
for(const auto &n:input)
{
hashed ^= n;
hashed *= FNV_prime;
}
return hashed;
}
};
template < typename T>
struct vector_hash<T,false> {
size_t operator()(std::vector<T> const &) const
{
std::cout << "No hash for you :-(\n";
return 0;
}
};
namespace std {
template< typename dtype >
struct hash< std::vector<dtype> > : vector_hash<dtype> {};
} // namespace std
int main() {
{
std::vector<int> v{1,2,3,4};
size_t hash = std::hash<std::vector<int>>{}(v);
std::cout << hash << "\n";
}
{
std::vector<std::string> v{"Hello", "world!"};
size_t hash = std::hash<std::vector<std::string>>{}(v);
std::cout << hash << "\n";
}
}
Live example
It is illegal to specialize a template in namespace std, unless you do it on a user provuded type. Vector is not user provided.
What you need to do is:
namespace helper{
template<class T, class=void>
struct hash:std::hash<T>{};
}
now you can do usual sfinae tricks with helper's hash, or extend it willy-nilly.
namespace helper {
template <typename dtype>
struct hash<std::vector<dtype>,
std::enable_if_t< std::is_arithmetic<dtype>::value>
> {
size_t operator()(const std::vector<dtype> &input) const {
//perform hash
}
};
}
Simply pass helper::hash<T> in place of std hash. The extra void defaulted parameter permits sfina specialization, the base spec forwards std hash, and there is no ill-formedness issues.
I have a lot of code that currently works with dynamic size vectors (such as std::vector, Eigen::VectorXd, ...) and I would like it to work also with static size vectors (such as std::array, Eigen::Vector3d, ...). My code is templatized with respect to TVector in such a way that it assumes that TVector has just size and operator[]. But the big problem is construction.
There are no common grounds when it comes to construction of both static and dynamic vectors. I have decided to replace all calls to the constructor of TVector by the following hypothetical function:
template <typename TVector>
TVector createVector(std::size_t sizeAtInitialization)
{
if (TVector has constructor taking an integral type)
return TVector(sizeAtInitialization);
else
return TVector(); // sizeAtInitialization ignored
}
Such that a generic call to createVector<TVector> will become createVector<std::vector<double>>(3) or createVector<std::array<double, 3>>(3).
std::is_default_constructible will not help me here, since both vector types are default constructible.
However, I am not sure that such a thing is even possible.
I have studied the static if here and member function detection here. It all seems extremely complicated and since the static_if uses lambdas which must return to an intermediate result, which must already be constructed, I am not sure it leads anywhere.
You can use std::is_constructible together with a bit of sfinae and std::enable_if
using namespace std;
template <class T>
using IntegerConstructible =
typename enable_if<is_constructible<T, int>::value, T>::type;
template <class T>
using NotIntegerConstructible =
typename enable_if<!is_constructible<T, int>::value, T>::type;
template<class T>
auto createVector(int size)
-> IntegerConstructible<T> {
return {size};
}
template<class T>
auto createVector(int size)
-> NotIntegerConstructible<T>{
return {};
}
int main(){
auto x = createVector<std::vector<int>>(3);
auto y = createVector<std::array<int,3>>(3);
return 0;
}
IntegerConstructible and NotIntegerConstructible are alias templates which are defined as long as the template argument can (or can't) be constructed. When defined
IntegerConstructible<T> = T.
So only one of the two createVector functions has a valid return type, the other one cannot be called. This allows the compiler to choose the right overload.
I love SFINAE (+1 for Tim) but I think that tag-dispatcing is clearer for this type of problem
#include <array>
#include <vector>
#include <iostream>
#include <type_traits>
template <typename T>
T cVH (int size, std::true_type const &)
{ std::cout << "with size" << std::endl; return { size }; }
template <typename T>
T cVH (int, std::false_type const &)
{ std::cout << "without size" << std::endl; return { }; }
template <typename T>
T createVector (int size)
{ return cVH<T>(size, typename std::is_constructible<T, int>::type{}); }
int main()
{
auto x = createVector<std::vector<int>>(3); // print "with size"
auto y = createVector<std::array<int,3>>(3); // print "without size"
}
--- EDIT ---
If there isn't a type-traits that can select the right value for all your tyes, you can create one yourself as (struct withSize) follows
#include <array>
#include <vector>
#include <iostream>
#include <type_traits>
template <typename>
struct withSize;
template <typename T>
struct withSize<std::vector<T>>
{ using type = std::true_type; };
template <typename T, std::size_t N>
struct withSize<std::array<T, N>>
{ using type = std::false_type; };
// others specializations of withSize for Eigen::Vector3d, Eigen::Matrix, etc.
template <typename T>
T cVH (int size, std::true_type const &)
{ std::cout << "with size" << std::endl; return { size }; }
template <typename T>
T cVH (int, std::false_type const &)
{ std::cout << "without size" << std::endl; return { }; }
template <typename T>
T createVector (int size)
{ return cVH<T>(size, typename withSize<T>::type{}); }
int main()
{
auto x = createVector<std::vector<int>>(3); // print "with size"
auto y = createVector<std::array<int,3>>(3); // print "without size"
}
I am new to SFINAE. I have a template that I would like to be able to accept classes that the size could be determined simply calling sizeof(x) or in case the value is dynamic it will require x.size().
I am trying to wrap my head around how as smooth as possible this could looks like and I think interface: size_t size(const Item& item) seems to be good enough.
The following is an example that works:
#include <iostream>
#include <cstdio>
#include <type_traits>
template <typename T>
class Fixed {
public:
typedef T Item;
static const bool kFixedSize = true;
static size_t size() {
return sizeof(T);
}
};
template <typename T>
class Dynamic {
public:
typedef T Item;
static const bool kFixedSize = false;
static size_t size(const T& item) {
return item.size();
}
};
template <typename T>
class Serialize {
public:
template <typename = typename std::enable_if<T::kFixedSize> >
size_t size(typename T::Item&) {
return T::size();
}
template <typename = typename std::enable_if<!T::kFixedSize> >
size_t size(const typename T::Item& item) {
return T::size(item);
}
};
int main() {
Serialize< Fixed<int> > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
Serialize< Dynamic<std::string> > dynamic;
std::cout << dynamic.size("string") << std::endl;
return 0;
}
It has an issues though one is: size_t size(typename T::Item&) and the other is size_t size(const typename T::Item& item) else the compiler compliance that I am overloading the template. The second is it seems like too match very tricky code to achieve the goal - is there better ways to do this?
I believe you want something like this
//class hierarchy to set the priority for type matching
struct second_priority
{
};
struct first_priority : public second_priority
{};
template<typename T>
auto size_impl(T const & data, second_priority t) -> int
{
return sizeof(data);
}
template<typename T>
auto size_impl(T const & data , first_priority t) -> decltype(data.size(),int())
{
return data.size();
}
template<typename T>
int size(T const & data )
{
return size_impl(data,first_priority{});
}
I think #Gautam Jha presented a nice solution using SFINAE. You can shorten it a bit by using ellipsis for the 'else' case, so you don't need to use this auxiliary class and it's inheritance:
template<typename T>
auto size_impl(T const & item, int) -> decltype(item.size())
{
return item.size();
}
template<typename T>
auto size_impl(T const & item, ...) -> size_t
{
return sizeof(T);
}
template<typename T>
auto size(T const & item) -> size_t
{
return size_impl(item, 0);
}
It's cool that you're playing around with SFINAE, but usually there are simpler (i.e. to read and to understand) ways to achieve the same, see the solution of POW (which has unfortunately been deleted).
Since all you want to do is call different functions to get the size in Dynamic or Fixed, you can just implement these classes differently and use them in Serialize:
#include <iostream>
#include <cstdio>
#include <type_traits>
template <typename T>
class Fixed {
public:
typedef T Item;
static size_t size(const T&) {
return sizeof(T);
}
};
template <typename T>
class Dynamic {
public:
typedef T Item;
static size_t size(const T& item) {
return item.size();
}
};
template <typename T>
class Serialize {
public:
size_t size(typename T::Item const& x) {
return T::size(x);
}
};
int main() {
Serialize< Fixed<int> > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
Serialize< Dynamic<std::string> > dynamic;
std::cout << dynamic.size( std::string{"string"} ) << std::endl;
return 0;
}
However, I would consider using a type-trait or a free function to do the same. This would be more extensible, because you have to just provide a new trait or an overload for new types, e.g. some container which has only a length method.
#include <iostream>
#include <cstdio>
#include <type_traits>
size_t size(int) {return sizeof(int);}
size_t size(std::string const& s) {return s.size();}
template<typename T>
struct size_trait
{
};
template<>
struct size_trait<int>
{
static size_t size(int) {return sizeof(int);}
};
template<>
struct size_trait<std::string>
{
static size_t size(std::string const& x) {return x.size();}
};
template <typename T>
class Serialize {
public:
size_t size(T const& x) {
return ::size(x);
}
size_t size_(T const& x) {
return size_trait<T>::size(x);
}
};
int main() {
Serialize< int > fixed;
int a = 0;
std::cout << fixed.size(a) << std::endl;
std::cout << fixed.size_(a) << std::endl;
Serialize< std::string > dynamic;
std::cout << dynamic.size( std::string{"string"} ) << std::endl;
std::cout << dynamic.size_( std::string{"string"} ) << std::endl;
return 0;
}
I'm trying to make a simple way to generate std::array's at compile time. It's been a struggle so far to figure out a good way to pass a constexpr function in at compile time. The workaround I have found so far is like this.
#include <iostream>
#include <array>
namespace a {
constexpr int f(const int & i) { return i * i * i;}
#include "generate_with_function.hpp"
}
int main()
{
auto arr = a::generator<false,10,0>::array;
for (auto i : arr) {
std::cout << i << " ";
}
return 0;
}
this basically assumes you will define a function called f and I wrapped it in a namespace incase I wanted to do a different one. I wanted to know if there is a more clever way to pass in the function and use it at compile time. Also here is the code that makes the list.
template <bool B, size_t Count,int ... Nums>
struct generator;
template <size_t Count>
struct generator<false,Count,0>
{
constexpr static std::array<int,Count> array
= generator<false,Count,1,f(0)>::array;
};
template <size_t Count, int Current, int ... Results>
struct generator<false,Count,Current, Results...>
{
constexpr static std::array<int,Count> array
= generator<Current+1==Count,Count,Current+1,f(Current), Results...>::array;
};
template <size_t Count, int Current, int ... Results>
struct generator<true,Count,Current,Results...>
{
constexpr static std::array<int,Count> array{{Results...}};
};
and before you ask no I don't actually have a real need for this.
As noted by #us2012 I should be specific about what I would rather have.
nowrapping in namespace
having to write the function but not actually passing it anywhere
and not requiring the function to be named f
You can actually use the function as a template parameter, here called Gen:
template <bool B, size_t Count, int Current, int Gen(size_t), int ... Nums>
struct generator;
template <size_t Count, int Current, int Gen(size_t), int ... Results>
struct generator<false,Count,Current, Gen, Results...>
{
constexpr static std::array<int,Count> array
generator<Current+1==Count,Count,Current+1,Gen,
Gen(Current), Results...>::array;
};
template <size_t Count, int Current, int Gen(size_t), int ... Results>
struct generator<true,Count,Current,Gen,Results...>
{
constexpr static std::array<int,Count> array{{Results...}};
};
With this it actually works to pass a constexpr function to the template (if the type matches exactly):
// helper to hide the "internal" template parameters
template <size_t Count, int Gen(size_t)>
struct gen {
constexpr static std::array<int, Count> array = generator<false, Count, 0, Gen>::array;
};
constexpr int f(size_t i) { return i * i * i; }
int main()
{
auto arr = gen<10,f>::array;
for (auto i : arr) {
std::cout << i << " ";
}
return 0;
}
You can also switch around the Gen(Current) and Results... parameters to get the values at the "correct" array indexes.