This is OK:
template<typename T>
using MyVector = std::vector<T>;
MyVector<int> xyz;
But not this:
template <typename F>
using MyCalc = float calc1(F f) { return -1.0f * f(3.3f) + 666.0f; }
though
template <typename F>
float calc1(F f) { return -1.0f * f(3.3f) + 666.0f; }
is OK. Is there a way to define an alias for calc1?
using name = thing declares a type alias. calc1 is a template function, not a type. It's no different from declaring a variable and trying to use using to declare an alias to it.
There is no way to declare a function alias. There are many problems with doing so, due to C++'s various rules. Do you want the alias to be for an entire overload set or just one specific function? Should the alias include ADL or not? And so forth.
Related
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 ]
I've stumbled upon something I can't get through since last week...
Having this:
template<typename> struct fx;
template<typename R, typename...Args>
struct fx<R(Args...)>
{
virtual R operator()(const Args & ...x) const = 0;
};
and this:
template<typename> struct fx_err;
// I feel here something is wrong, but I can't figure it out.
template<template<typename> class F, typename R, typename... Args>
struct fx_err< F<R(Args...)> > : fx<R(R,Args...)>
{
using fx_type = F<R(Args...)>;
fx_type f;
R operator ()(const R &y, const Args & ...x) const override
{
return y - f(x...);
}
};
and this:
struct example_fun : fx<int(int,int,int)>
{
int operator() (const int &a, const int &b, const int &c) const override
{
return a * b * c;
}
};
when finally I try to use it like:
fx_err<example_fun> example;
int err = example(24,2,3,4);
compiler throws error: 'example has incomplete type'.
Something similar works only if I do not specialize fx_err and use pointer to fx_type functor instead, but then I need to add constructor to grab the pointer itself which is not something I want.
It's very frustrating. What's wrong with this? Is it possible what I'm trying to achieve? Can anybody help?
Thanks in advance.
UPDATE:
here's example code to play around with for those willing to experiment with this example: http://pastebin.com/i3bRF8tB
The problem on line:
fx_err<example_fun> example;
is caused by the fact that example_fun is "passed" to fx_err, which selects the declaration:
template<typename> struct fx_err;
which is an incomplete type.
The specialization you provide:
// I feel here something is wrong, but I can't figure it out.
template<template<typename> class F, typename R, typename... Args>
struct fx_err< F<R(Args...)> > : fx<R(R,Args...)>
{ ... }
cannot be selected, because example_fun is not a template class as required by:
template<typename> class F
Avoid template template parameters if you can. They add more complexity, and less flexibility, than you probably want.
It looks like you're trying to match the form of the fx base class against its derived class. Partial specialization requires exact matches, it won't slice to the base class. And even if it did, this member would be of abstract class type:
using fx_type = F<R(Args...)>;
fx_type f; // same as fx<R(Args...)> which is abstract
The solution is to preserve the derived class, and tell the partial specialization how to find the base. Then the partial specialization can do pattern matching on the base class.
template<typename derived, typename base = typename derived::fx>
struct fx_err;
template<typename derived, template<typename> class F, typename R, typename... Args>
struct fx_err< derived, F<R(Args...)> > : F<R(R,Args...)>
Live solution: http://coliru.stacked-crooked.com/a/870172bcad0a9034
Of course, finding the base class by typename derived::fx sort-of begs the question of what base class template was used. In theory, you could have several templates of the same name, or derived could have a member typedef my_base fx; instead of inheriting from an fx specialization.
More likely, though, you don't need template<typename> class F at all.
template<typename derived, typename base = typename derived::fx>
struct fx_err;
template<typename derived, typename R, typename... Args>
struct fx_err< derived, fx<R(Args...)> > : fx<R(R,Args...)>
fx_err<example_fun> does not match your partial specialization because example_fun is not of the form F<R(Args...)>. It inherits a type of that form, but that's not the same thing.
When selecting specializations for class templates, implicit conversions aren't considered. Therefore example_fun isn't seen as a fx<...> by the compiler when matching the specializations and the primary (undefined) template is chosen over the other specialization.
To solve this you can expose an alias for the base class in the derived class:
struct example_fun : fx<int(int,int,int)>
{
using type = fx<int(int,int,int)>;
};
And now use this alias at the declaration site:
fx_err<example_fun::type> example;
int err = example(24,2,3,4);
You can even use a macro to avoid repeating the base class name:
template<class T> struct tag { using type = T; };
#define BASE_TAG(B) B, public tag<B>
struct example_fun : BASE_TAG(fx<int(int, int, int)>) {
// ...
};
Your basic problem is that template type pattern matching does not work like function overload template pattern matching. Inheritance is ignored, only the type passed in is pattern matched against.
So struct foo: some_template<some_args...> does not match some_template<some_args...> during template type pattern matching for the purpose of figuring out which specialization to use.
This lets us work with types as values in functions:
template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;
Now function template pattern matching works more like what you seem to be expecting:
template<template<class...>class Z, class...Args>
constexpr tag<Z<Args...>> get_template( Z<Args...>const& ) { return {}; }
takes a single argument, does template function pattern matching and deduction against it. This will look at parents of the type passed in. It tries to match Z<Args...> for some template Z.
It returns a tag<Z<Args...>>, which is a stateless type that just stores the type we need. We can then feed the above through an alias to extract that template expansion:
template<class T>
using get_template_t = type_t<decltype(get_template(std::declval<T>()))>;
which is most of the way there.
Next, we need some SFINAE helper magic:
template<class...>struct voider:tag<void>{};
template<class...Ts>using void_t=type_t<voider<Ts...>>;
std::void_t is C++14, and takes a bunch of types and throws them away, returning void instead. I do it in 2 lines because some compilers fail on the one-line version.
Ok, now we attack fx_err:
template<class,class=void> struct fx_err;
the second class=void lets us do FSINAE work. We start with your
template<template<class...>class F, class R, class...Args>
struct fx_err< F<R(Args...)>, void > : fx<R(R,Args...)>
{
using fx_type = F<R(Args...)>;
fx_type f;
R operator ()(const R &y, const Args & ...x) const override {
return y - f(x...);
}
};
and we also do this:
template<class T>
struct fx_err< T, void_t<get_template_t<T>>> : fx_err<get_template_t<T>>
{};
which I think should work. If it doesn't, we just need to add a test to exclude the direct T<F(Args...)> case from this specialization.
I wish to iterate over the types in my boost::variant within my unit test. This can be done as follows:
TEST_F (MyTest, testExucutedForIntsOnly)
{
typedef boost::variant<int, char, bool, double> var;
boost::mpl::for_each<SyntaxTree::Command::types>(function());
...
}
Where function is a functor. I simply want to ensure that a particular operation occurs differently for one type in the variant with respect to all others. However, I don't like that the test is now done in another function -- and what if I wish to access members for MyTest from the functor? It seems really messy.
Any suggestions on a better approach?
So, you want to call a function on a boost::variant that is type-dependent?
Try this:
template<typename T>
struct RunOnlyOnType_Helper
{
std::function<void(T)> func;
template<typename U>
void operator()( U unused ) {}
void operator()( T t ) { func(t); }
RunOnlyOnType_Helper(std::function<void(T)> func_):func(func_){}
};
template<typename T, typename Variant>
void RunOnlyOnType( Variant v, std::function< void(T) > func )
{
boost::apply_visitor( RunOnlyOnType_Helper<T>(func), v );
}
The idea is that RunOnlyOnType is a function that takes a variant and a functor on a particular type from the variant, and executes the functor if and only if the type of the variant matches the functor.
Then you can do this:
typedef boost::variant<int, char, bool, double> var;
var v(int(7)); // create a variant which is an int that has value 7
std::string bob = "you fool!\n";
RunOnlyOnType<int>( v, [&](int value)->void
{
// code goes here, and it can see variables from enclosing scope
// the value of v as an int is passed in as the argument value
std::cout << "V is an int with value " << value << " and bob says " << bob;
});
Is that what you want?
Disclaimer: I have never touched boost::variant before, the above has not been compiled, and this is based off of quickly reading the boost docs. In addition, the use of std::function above is sub-optimal (you should be able to use templated functors all the way down -- heck, you can probably extract the type T from the type signature of the functor).
I've got a variant class. It has a pair of constructors:
/// Construct and fill.
template <typename T>
inline
variant (const T& t)
{
YYASSERT (sizeof (T) <= S);
new (buffer.raw) T(t);
}
template <typename T>
inline
variant (T&& t)
{
YYASSERT (sizeof (T) <= S);
new (buffer.raw) T(std::move(t));
}
Now I've called those constructors in this code:
parser::symbol_type
parser::make_IDENTIFIER (const Wide::ParsedFile::Identifier*& v)
{
return symbol_type (token::IDENTIFIER, v);
}
symbol_type takes a variant as it's second argument in this specific constructor, and v is being implicitly converted.
However, MSVC will try to use the rvalue reference constructor instead of using the other constructor, resulting in a compilation error when it attempts to new a reference. Why is that, and how can I make it stop?
You generally should not overload a templated T&& function. You should instead have the single function which forwards:
template <typename T>
inline
variant (T&& t)
{
typedef typename std::remove_reference<T>::type Tr;
YYASSERT (sizeof (Tr) <= S);
new (buffer.raw) Tr(std::forward<T>(t));
}
This has the functionality of your two overloads, while avoiding the problem of picking the wrong one.
I believe (not positive) that these are the two variants in your overload set:
varaint<const Wide::ParsedFile::Identifier*>(const Wide::ParsedFile::Identifier*const&)
varaint<const Wide::ParsedFile::Identifier*&>(const Wide::ParsedFile::Identifier*&)
And the second one wins because it is more specialized than the first (I'm making an educated guess, I'm not 100% positive).
The second template would be a better match, because the const specifiers are in different places in your function and in the first constructor.
In the first overload you will have T being deduced as
const Wide::ParsedFile::Identifier*
And then creating a const reference to that type. That adds an extra const.
In C++0x, I can do something like this:
double f(double x) { return x; }
template<class T>
T f(T x) = delete;
To prevent f() from being called on any other type than double.
What I'm trying to do is similar, however, not quite the same.
I have a function that operates on pointer arrays. For example:
template<class T>
T* some_string_function(T* x);
I want to be able to make T work for char, char16_t, and char32_t, but not any other type. I was thinking that C++0x's delete would be a good way to accomplish this. Basically, I want to be able to prevent this function from working with any type that isn't one of the three Unicode char types, but I still want to have the benefits of function templates, which allow me to generalise types and avoid repeating code.
What would be the best way to solve this problem? Is it possible?
Use boost::enable_if, along with type traits.
template<class T>
T* some_string_function(T* x, boost::enable_if<is_char_type<T>);
(assuming is_char_type is a type trait you define, which evaluates to true for the desired types, and false for all others)
You could do it using type_traits:
template<typename T>
typename enable_if<is_same<char, T>::value || is_same<char16_t, T>::value || is_same<char32_t, T>::value, T*>::type some_string_function(T *x)
{
return x;
}
Though you'd have to specifically specify const as well if you want to allow that.
I think the best way to do it is using a combination of static_assert and is_same (Both C++0x features). This also allows for a more friendly error message when you make an invalid call to the function.
#include <iostream>
using namespace std;
template<typename T> T* f(T*)
{
static_assert
(is_same<T, char>::value
|| is_same<T, char16_t>::value
|| is_same<T, char32_t>::value,
"Invalid Type, only char pointers allowed");
}
int main()
{
cout<<*f(new char('c'));//Compiles
cout<<*f(new int(3));//Error
}