I am trying to compile the below code, and I am getting the error as
"error: ‘MD5Sum’ is not a class template
template<> struct MD5Sum<::cv_bridge::CvImage>"
template<> struct MD5Sum<::cv_bridge::CvImage>
{
static const char* value() { return MD5Sum<::sensor_msgs::msg::Image>::value(); }
static const char* value(const ::cv_bridge::CvImage&) { return value(); }
static const uint64_t static_value1 = MD5Sum<::sensor_msgs::msg::Image>::static_value1;
static const uint64_t static_value2 = MD5Sum<::sensor_msgs::msg::Image>::static_value2;
// If the definition of sensor_msgs/Image changes, we'll get a compile error here.
ROS_STATIC_ASSERT(MD5Sum<::sensor_msgs::msg::Image>::static_value1 == 0x060021388200f6f0ULL);
ROS_STATIC_ASSERT(MD5Sum<::sensor_msgs::msg::Image>::static_value2 == 0xf447d0fcd9c64743ULL);
};
This seems to be template specialization. Does it means that template class should be present first before make template specialization out of it.
The class template MD5Sum needs to be declared before any of its specializations.
You either need to include the file where the template is declared, or declare it yourself.
You can use an empty definition (if you only want to call fully specialized versions) or the generic implementation you choose:
// add this before your specialization
template <class T> struct MD5Sum; // empty declaration
// or your default implementation
template <class T> struct MD5Sum {
...
};
Related
In C# or Java, the following does not compile, because I "forgot" the where part in class declaration, that specifies that T is instance of something that defines the add method.
class C<T> {
T make(T t) {
return t.add(t);
}
}
I'd like to get similar compile-time check in C++, if I specify incomplete requires for a template argument.
template <typename T>
requires true
class C {
public:
T make() {
return T{};
}
};
I'd like to get a compile error for the C++ code above, stating that method c.make relies on T being default-constructible, which is however not captured in the requires constraints on T.
Can I get the compiler to check that my set of requires constraints is sufficient to cover everything the class implementation does?
I am using gcc (GCC) 10.0.0 20191207 (experimental) for this.
What I want is called definition checking, and apparently it is not possible currently
C++2a concepts (formerly known as “Concepts Lite” and/or the Concepts TS) famously do not support “definition checking.” The idea of definition checking is that the programmer might write [...]
https://quuxplusone.github.io/blog/2019/07/22/definition-checking-with-if-constexpr/
8.2 Definition checking
Concepts currently do not prevent a template from using operations that are not specified in the requirements. Consider:
template<Number N>
void algo(vector<N>& v){
for (auto& x : v) x%=2;
}
Our Number concept does not require %=, so whether a call of algo succeeds will depend not just on what is checked by the concept, but on the actual properties of the argument type: does the argument type have %=? If not, we get a late (instantiation time) error.
Some consider this a serious error. I don’t [...]
http://www.w.stroustrup.com/good_concepts.pdf
The current proposal checks interfaces and that's where the main benefits for users are, but not template definitions. That has been explicit from the start.
https://isocpp.org/blog/2016/02/a-bit-of-background-for-concepts-and-cpp17-bjarne-stroustrup
template <class T>
requires std::is_default_constructible_v<T>
class C
{
static_assert(std::is_default_constructible_v<T>,
"T is not default-constructible");
};
struct valid
{
};
class invalid
{
invalid() = delete;
};
int main()
{
C<valid>();
// C<invalid>(); // assertion fails.
}
You can write static_assert anywhere inside the class definition, alongside with requires. That will give you an error message you want.
UPDATE After reading the link you have provided, I suppose you just need multiple checks.
You can write a traits struct:
// SFINAE to check if has "add"
template <class T, class = std::void_t<>>
struct has_method_add
{
constexpr static bool value = false;
};
template <class T>
struct has_method_add<T, std::void_t<decltype(&T::add)>>
{
constexpr static bool value = true;
};
template <class T, class = std::void_t<>>
struct has_operator_remainder
{
constexpr static bool value = false;
};
template <class T>
struct has_operator_remainder<T, std::void_t<decltype(&T::operator%=)>>
{
constexpr static bool value = true;
};
template <class T>
struct error_missing_add
{
constexpr static bool value = has_method_add<T>::value;
static_assert(has_method_add<T>::value, "T::add is not defined");
};
template <class T>
struct error_missing_remainder
{
constexpr static bool value = has_operator_remainder<T>::value;
static_assert(has_operator_remainder<T>::value, "T::operator%= is not defined");
};
template <class T>
class C
{
static_assert(std::conjunction_v<error_missing_add<T>, error_missing_remainder<T>>);
// impl...
};
struct valid
{
void add();
int operator%=(int) const;
};
struct missing_add
{
int operator%=(int) const;
};
struct missing_remainder
{
void add();
};
int main()
{
C<valid>{};
C<missing_add>{}; // error: T::add is not defined
C<missing_remainder>{}; // error: T::operator%= is not defined
return 0;
}
I am trying to write a template using the CRTP pattern. What I would like is for the template to access a static const in the templated class.
My template look like this in it's own header:
template <class T> foo {
static const int readValue = T::value
}
And I inherit from the template like this (in another header file):
class fooImpl: foo<fooImpl> {
static const int value = 42;
}
However, clang complains:
No member named 'value' in 'fooImpl'
I think I get the chicken and egg problem here. The template does not know the definition of fooImpl, and hence, cannot know that it has the member value when it is instantiated.
But how do I work around it? Is there a way to get the compile time propagation of the const value into the instantiated template?
The foo<fooImpl> base class is instantiated in the base-class list but fooImpl is an incomplete type at that point, and foo::value has not been declared yet.
You can move the definition of the static member later:
template <class T> struct foo {
static const int readValue;
};
class fooImpl: foo<fooImpl> {
static const int value = 42;
};
template<class T> const int foo<T>::readValue = T::value;
However, this won't allow you to use readValue as a compile-time constant in the body of foo.
I have a templated class with an templated member function
template<class T>
class A {
public:
template<class CT>
CT function();
};
Now I want to specialize the templated member function in 2 ways. First for having the same type as the class:
template<class T>
template<> // Line gcc gives an error for, see below
T A<T>::function<T>() {
return (T)0.0;
}
Second for type bool:
template<class T>
template<>
bool A<T>::function<bool>() {
return false;
}
Here is how I am trying to test it:
int main() {
A<double> a;
bool b = a.function<bool>();
double d = a.function<double>();
}
Now gcc gives me for the line marked above:
error: invalid explicit specialization before ‘>’ token
error: enclosing class templates are not explicitly specialize
So gcc is telling me, that I have to specialize A, if I want to specialize function, right?
I do not want to do that, I want the type of the outer class to be open ...
Is the final answer: it is not possible? Or is there a way?
Yes, this is the problem:
error: enclosing class templates are not explicitly specialized
You cannot specialize a member without also specializing the class.
What you can do is put the code from function in a separate class and specialize that, much like basic_string depends on a separate char_traits class. Then then non-specialized function can call a helper in the traits class.
You can use overload, if you change the implementation.
template <typename T>
class Foo
{
public:
template <typename CT>
CT function() { return helper((CT*)0); }
private:
template <typename CT>
CT helper(CT*);
T helper(T*) { return (T)0.0; }
bool helper(bool*) { return false; }
};
Simple and easy :)
When I try to compile this with Clang
template<class T>
struct Field
{
char const *name;
Field(char const *name) : name(name) { }
};
template<class Derived>
class CRTP { static Field<Derived> const _field; };
class Class : public CRTP<Class> { };
Field<Class> const CRTP<Class>::_field("blah");
int main() { }
I get
error: template specialization requires 'template<>'
Field<Class> const CRTP<Class>::_field("blah");
~~~~~~~~~~~ ^
I don't understand the error at all. What is wrong with my definition of _field and how do I fix it?
(Note that the arguments to _field are not necessarily the same for all subclasses.)
For the compiler to identify this as a template specialization (e.g. to be able to check the syntax), you need the template keyword:
template<>
Field<Class> const CRTP<Class>::_field("blah");
Its brackets are empty as all template parameters are specialized, but you cannot just leave it away.
The error says exactly what is missing. template<> is missing before that line.
template<>
Field<Class> const CRTP<Class>::_field("blah");
Note, however, that your typing of Field<Class>, if unique, could be used to construct all instances of Field<Class> with a given string.
template<typename T>
struct field_trait;
template<class T>
struct Field
{
char const *name;
Field() : name(field_trait<T>::get_name()) {}
};
template<class Derived>
class CRTP { static Field<Derived> const _field; };
template<class Derived>
class CRTP<Derived>::_field;
class Class;
template<>
struct field_traits<Class> {
static const char* get_name() { return "blah"; }
};
class Class : public CRTP<Class> { };
int main() { }
which means that every instance of Field<Class> always has the name "blah".
One question I would have is, do you really need storage for said Field<Class> to actually have a pointer to a string, and if so does it need to be unique, and if so does it need to be "bare"? Because figuring out where the static instance exists is somewhat annoying.
Together with field_traits above:
template<class Derived>
class CRTP { static Field<Derived>& field() const { static Field<Derived> _field( field_traits<Derived>::get_name()); return _field; };
this moves the problem of "where is the _field stored" to being the compilers problem. And it is initialized by the contents of field_traits<T>::get_name().
A static data member must have both a declaration and a definition. If this was a plain class it would look like this:
// header:
class C {
static int i;
};
// source:
int C::i = 3;
Templates aren't ordinarily defined in source files, so the code would look something like this:
// header:
template <class T>
class C {
static int i;
};
template <class T>
int C<T>::i = 3;
In your code, you don't have the definition of the static data member. That's okay if you don't use it. But the code that the compiler is complaining about defines a static data member for CRTP<Class>; that's a specialization (because it's not applicable to all instantiations of CRTP, just to this one), and the compiler is saying that you have to tell it that it's a specialization. So do as you're told:
template <>
Field<Class> const CRTP<Class>::_field("blah");
or, to write the non-specialized template version, use the usual template syntax:
template <class T>
Field<T> const CRTP<T>::_field("blah");
How should I initialize a static variable for a partial specialization?
template <bool A=true, bool B=false>
struct from {
const static std::string value;
};
// no specialization - works
template <bool A, bool B>
const std::string from<A, B>::value = "";
// partial specialization - does not compile -
// Error: template argument list following class template name must list parameters in the order used in template parameter list
// Error: from<A,B>' : too few template arguments
template <bool B>
const std::string from<true, B>::value = "";
// full specialization - works
const std::string from<false, true>::value = "";
Why doesn't the partial work?
EDIT: I found a solution based on Partial template specialization for initialization of static data members of template classes
I need to repeat the declaration for the partial specialization before it allowed me to initialize the static variable:
template <bool B>
struct from<true, B> {
const static std::string value;
};
Again, the question is why?
Partial specialization of members (whether they're functions or static data) are not allowed without partial specialization of enclosing class template itself.
That is, you have to specialize the class template also. So the following should work:
//partial specialization of class template
template <bool B>
struct from<true, B> {
const static std::string value;
};
//now you can do this!
template <bool B>
const std::string from<true, B>::value = ""
Also, this will not compile (have you tried compiling this?):
// full specialization - works (SORRY, IT WILL NOT WORK!)
const std::string from<false, true>::value = ""; //this should be an error
You've to write this:
// full specialization
template<> //<---- this is important!
const std::string from<false, true>::value = ""
Here's a working full specialization of the template.
#include <string>
#include <iostream>
template <bool A=true, bool B=false>
struct from {
const static std::string value;
};
// no specialization - works
template <bool A, bool B>
const std::string from<A, B>::value = "no specialization";
// full specialization, note the empty template parameter list
template <>
const std::string from<true, true>::value = "<true,true> specialization";
int main() {
std::cout << from<false, false>::value << std::endl;
std::cout << from<true, true>::value << std::endl;
}
You found the correct way of defining the partial.
The reason for your partial not working is that you need to declare the structure type before being able to provide an initialization for its static field. The partial specialization is a template in its own right, and deserves a definition.
The full specialization is actually a type instance of the initial template, and thus doesn't need to be defined separately.