Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Remove the last argument from a parameter pack

147 views
Skip to first unread message

aitor....@googlemail.com

unread,
Dec 13, 2018, 3:43:17โ€ฏAM12/13/18
to
Hi,

I'm trying to call a function from another template function but removing the last argument passed.

I need it because I've made a delegate implementation where one function call another one and works fine, but the problems is when the destination function has fewer arguments than the emitter function.

Is there any way the remove the last argument(s) from a parameter pack?

example:

template<typename... Args>
void invoke(string otherVariable, Args... args)
{
// call it but without the last argument
destinationFunction(args...);
}

void destinationFunction(string s, int val, bool status)
{
std::cout << s << " val:" << val << " status:" << status;
}

int main()
{
invoke("text", 1, true, 2);

// invoke should call destinationFunction but without the argument "2"
}

Can someone help me?

Alf P. Steinbach

unread,
Dec 13, 2018, 6:48:15โ€ฏAM12/13/18
to
On 13.12.2018 09:43, aitor....@googlemail.com wrote:
> template<typename... Args>
> void invoke(string otherVariable, Args... args)
> {
> // call it but without the last argument
> destinationFunction(args...);
> }
>
> void destinationFunction(string s, int val, bool status)
> {
> std::cout << s << " val:" << val << " status:" << status;
> }
>
> int main()
> {
> invoke("text", 1, true, 2);
>
> // invoke should call destinationFunction but without the argument "2"

The presence of an unused last argument is IMO a design odour.

But given that the problem needs to be solved anyway, I would probably
use an `index_list` with tuple `tie` and `get`.

A C++03 style solution could be to reason that it's easy to omit the
first argument of an argument pack, and that one can reverse an argument
pack recursively, but then C++03 didn't have argument packs.

Cheers & hth.,

- Alf

User

unread,
Dec 13, 2018, 9:18:47โ€ฏAM12/13/18
to
Hi,

the presence of unused argument isn't a design decision, but working with delegates. A function of the type EmitterFunc(int, bool, int) can be connected to a function with the prototype ReceptorFunction(int, bool).

Thanks for your suggestion of tuple and get. But I still don't know how to remove the last element of the list. Is there an easy way to remove the nth element of the argument list and still call the destination function?

Thanks again!

Richard

unread,
Dec 13, 2018, 12:43:05โ€ฏPM12/13/18
to
[Please do not mail me a copy of your followup]

User <aitor....@googlemail.com> spake the secret code
<1d46e37a-e16e-4715...@googlegroups.com> thusly:

>the presence of unused argument isn't a design decision, but working
>with delegates. A function of the type EmitterFunc(int, bool, int) can
>be connected to a function with the prototype ReceptorFunction(int,
>bool).

Delegates are not in the C++ language, so your statement seems
disconnected from C++.

Alf's point is that it's a design error to directly connect functions
with mismatching signatures.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

james...@alumni.caltech.edu

unread,
Dec 13, 2018, 1:05:30โ€ฏPM12/13/18
to
On Thursday, December 13, 2018 at 12:43:05 PM UTC-5, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> User <aitor....@googlemail.com> spake the secret code
> <1d46e37a-e16e-4715...@googlegroups.com> thusly:
>
> >the presence of unused argument isn't a design decision, but working
> >with delegates. A function of the type EmitterFunc(int, bool, int) can
> >be connected to a function with the prototype ReceptorFunction(int,
> >bool).
>
> Delegates are not in the C++ language, so your statement seems
> disconnected from C++.
>
> Alf's point is that it's a design error to directly connect functions
> with mismatching signatures.

Not necessarily. If Emittor() is used as a callback function, the caller
of Emittor() might require it to have an extra parameter just because
some, but not all, of the possible callback functions need to use that
extra parameter - and Emittor might be one that doesn't need it. That
would constitute neither a design error in Emittor(), nor a design error
in it's caller. Emittor() serves only as an adaptor to allow it's caller
to indirectly call ReceptorFunction(), despite the signature mismatch.

Alf P. Steinbach

unread,
Dec 13, 2018, 4:16:29โ€ฏPM12/13/18
to
Thanks. I didn't think of that, and I still have some difficulty seeing
how a function template is used as a callback. Here's some concrete
code, it would be nice if you could exemplify how to use `foo` as some
kind of callback (I tried to use it as template parameter, but failed):

----------------------------------------------------------------------------
#include <iostream>
#include <string> // std::string
#include <tuple> // std::(tie, get)
#include <utility> // std::(forward, make_index_sequence)
using namespace std;

// The OP's function "destinationFunction":
void destination_function( const string s, const int val, const bool
status )
{
cout << s << " val:" << val << " status:" << status << endl;
}

template< size_t... indices, class... Args >
void foo_adapter( index_sequence<indices...>, string s, Args&&... args )
{
const auto arg_refs = tie( args... );
destination_function( move( s ), get<indices>( arg_refs )... );
}

// The OP's function "invoke":
template< class... Args >
void foo( string s, Args&&... args )
{
foo_adapter(
make_index_sequence<sizeof...( args ) - 1>(),
move( s ),
forward<Args>( args )...
);
}

auto main() -> int
{
foo( "hm!", 42, true, 3.14 );
}
----------------------------------------------------------------------------

Cheers!,

- Alf

User

unread,
Dec 13, 2018, 4:49:42โ€ฏPM12/13/18
to
As pointed out by James, delegates accepts emitter functions which more arguments than the receptor, because they are discarded. Delegates aren't in C++, but pointer to member functions void (SomeClass::*Method)() yes, so could "easily" implement them.

emitterFunction(int, int, int) connected to receptorFunction(int, int, int)
connected to receptorFunction2(int, int)


I was doing a C++/Qt signals & slots implementation and worked nicely, but when I tried with functions of different arguments count I couldn't make it work with the templates. In reality I'm using pointer to member functions, but to make the example easier I used just function.

I've tried in the newest C++ and work (still don't understand completely, haha). Sadly in my Qt 5.11 version doesn't compile, it looks like that the Qt/C++11 cannot parse completely the parameter packs.

Thanks!

Chris Vine

unread,
Dec 13, 2018, 4:53:32โ€ฏPM12/13/18
to
Can you use a lambda expression as a shim? If so, just have the lambda
take all the arguments and apply the function it is wrapping with all
but the last one.

Chris Vine

unread,
Dec 13, 2018, 5:07:50โ€ฏPM12/13/18
to
On Thu, 13 Dec 2018 21:53:19 +0000
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
[snip]
> Can you use a lambda expression as a shim? If so, just have the lambda
> take all the arguments and apply the function it is wrapping with all
> but the last one.

Ah, but the parameters are variadic in number. So that won't work.

Chris Vine

unread,
Dec 13, 2018, 7:13:26โ€ฏPM12/13/18
to
On Thu, 13 Dec 2018 22:07:38 +0000
I am not entirely sure of what you are doing, but since your functions
are variadic I think the earlier suggestion of constructing a tuple and
applying it with an index list is the way to go.

The code below is a suggestion which does that. If you are using C++14
rather than C++11 you can construct the index list with a constexpr
function instead of a template struct. You will need to add in type
deduction on the return value if you want to apply a function with
other than a void return type.

In the code below, three arguments are applied to a lambda expression
taking two arguments.

******************

#include <tuple>
#include <utility>
#include <cstddef>
#include <iostream>

template<std::size_t... indices>
struct IndexList {
typedef IndexList<indices...> Type;
};

template<std::size_t count, std::size_t... indices>
struct MakeIndexList: public MakeIndexList<count - 1, count - 1,
indices...> {};

template<std::size_t... indices>
struct MakeIndexList<0, indices...>: public IndexList<indices...> {};

template <class Func, class Tuple, std::size_t... indices>
void apply_helper(Func&& func, Tuple&& t, IndexList<indices...>) {
func(std::get<indices>(std::forward<Tuple>(t))...);
}

template <class Func, class... Args>
void apply_except_last(Func&& func, std::tuple<Args...>&& t) {
typedef typename MakeIndexList<(sizeof...(Args)) - 1>::Type List;
apply_helper(std::forward<Func>(func), std::move(t), List());
}

template <class Func, class... Args>
void call_except_last(Func&& func, Args&&... args) {
apply_except_last(std::forward<Func>(func),
std::make_tuple(std::forward<Args>(args)...));
}

int main () {
auto callback = [](int a, int b) {std::cout << a + b << std::endl;};
call_except_last(callback, 5, 6, 7);
}

User

unread,
Dec 14, 2018, 7:15:23โ€ฏAM12/14/18
to
Thanks for your help,

the Alf's parameter pack solution worked, but the problem is another: the template and parameter pack works only with indices produces at compile time. The problem is what happens when argument's count isn't a constant but a variable:

int numberOfArgumentsToRemove = 1;
template<Args... args> invoke()

for that the templates doesn't work. But it's ok, maybe with variants and other mechanisms is possible.

Chris Vine

unread,
Dec 14, 2018, 8:41:43โ€ฏAM12/14/18
to
Ah, I hadn't seen Alf's coded solution until after I had posted mine.
Either it hadn't arrived on my news server or I missed it. Mine is
slightly more efficient as it avoids creating any intermediate
lvalues. In fact with -O1 and above

call_except_last(callback, 5, 6, 7)

produces the same object code as

callback(5, 6);

and it should do so with non-trivial argument types as well (not
tested).

On re-reading my version, it would be clearer to combine
call_except_last() and apply_except_last() into a single function (and
in case you were wondering, there is no lifetime problem with this for
the temporary tuple, as its lifetime is bound to the reference 't'):

template <class Func, class... Args>
void call_except_last(Func&& func, Args&&... args) {
typedef typename MakeIndexList<sizeof...(Args) - 1>::Type List;
auto&& t = std::make_tuple(std::forward<Args>(args)...);
apply_helper(std::forward<Func>(func), std::move(t), List());
}

On your latest question, you can use my/Alf's approach if the number of
arguments to pass to the target function is known at compile time. If
you cannot deduce that, then one alternative approach would be to have a
target function taking a std::vector or std::list object and construct
the vector or list recursively for the required number of iterations as
you peal arguments off, or to arrange the function somewhat like
std::printf.

However I have real difficulty in understanding your use case.

User

unread,
Dec 14, 2018, 2:42:38โ€ฏPM12/14/18
to
> However I have real difficulty in understanding your use case.

The idea is to implement the Qt signals & slots, delegates. I give you an example:


class Emitter {
public: /** signals: **/
void clicked(int x, bool status, int other);
};

class Receptor {
public:
void buttonClicked(int value, bool status){
qDebug() << "buttonClicked" << value << status;
}
};

int main(){
Emitter* emitter = new Emitter;
Receptor* receptor = new Receptor;

// the emitter save the objects to be called later
connect(emitter, &Emitter::clicked, receptor, &Receptor::buttonClicked);

...
// later in code

// our function is emitted and the connected functions must be called
emitter->clicked();

// here is the problem, I can know that one argument must be omitted, but
// there is no way to remove it with the parameter pack

}

james...@alumni.caltech.edu

unread,
Dec 14, 2018, 3:54:11โ€ฏPM12/14/18
to
According to <http://doc.qt.io/qt-5/signalsandslots.html>,
"a slot may have a shorter signature than the signal it receives because it can ignore extra arguments".

Chris M. Thomasson

unread,
Dec 14, 2018, 10:22:40โ€ฏPM12/14/18
to
Nice. I can use this for other things.

Chris Vine

unread,
Dec 15, 2018, 6:26:02โ€ฏAM12/15/18
to
I still don't think that I have grasped your problem. If you are
writing your own implementation of a signal/slot framework, when
invoking the receiving object's member function then, from the arguments
supplied by the emitter, only pass it the number of arguments which in
fact represents the receiving function's arity.

You (the programmer invoking 'connect') must know the arity of the
receiving member function that you are "connecting" in your code and
which the signal will dispatch. This arity which you must know could be
passed in as a function parameter of 'connect', or you could derive it
programmatically: see an example below - you would need overloads of
the get_arity() function in order to cover const and non-const member
functions, but that is a task for you. Since the get_arity() function
is constexpr, you could use it together with the tuple and index list
approach, but that seems like overkill: instead you could drop the
surplus arguments as a runtime operation when invoking the receiving
function.

Presumably your connect function is a template function so there is
lots more work for you to do if you are writing your own generic
signal/slot framework.

**********************

#include <cstddef>
#include <iostream>

void my_func2(int a, int b) {}
void my_func3(int a, int b, int c) {}

template <class Ret, class... Args>
constexpr std::size_t get_arity(Ret(*)(Args...)) {
return sizeof...(Args);
}

int main () {
std::cout << get_arity(my_func2) << std::endl;
std::cout << get_arity(my_func3) << std::endl;
}

Chris Vine

unread,
Dec 15, 2018, 7:44:57โ€ฏAM12/15/18
to
On Sat, 15 Dec 2018 11:25:47 +0000
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
> or you could derive [the arity]
> programmatically: see an example below - you would need overloads of
> the get_arity() function in order to cover const and non-const member
> functions, but that is a task for you. Since the get_arity() function
> is constexpr, you could use it together with the tuple and index list
> approach, but that seems like overkill: instead you could drop the
> surplus arguments as a runtime operation when invoking the receiving
> function.

By the way, this get_arity() function will not work with lambda
expressions. But that is fine - a lambda expression is a function
literal supplied by the programmer on the fly. You can document that if
passing a lambda expression to your connect() function, then the
signature of the lambda expression must match the signal's signature
exactly, even if some arguments are unused in the lambda.

You can detect lambdas by having a templated catch-all of 'get_arity'
for cases where there is no better match, which returns say size_t(-1)
to indicate that the arity cannot be deduced. In such a case, you
can pass on all the emitter's arguments to the lambda.

// where there is no better match
template <class Func>
constexpr std::size_t get_arity(Func&&) {
return (std::size_t) -1;
}

Christian Gollwitzer

unread,
Dec 15, 2018, 4:43:10โ€ฏPM12/15/18
to
Am 14.12.18 um 20:42 schrieb User:
>> However I have real difficulty in understanding your use case.
>
> The idea is to implement the Qt signals & slots, delegates. I give you an example:
>
>
> class Emitter {
> public: /** signals: **/
> void clicked(int x, bool status, int other);
> };
> [...]

Have you checked how this was solved by other frameworks? Qt uses a
special compiler and runtime string comparison. But there is another
library called libsigc++ with a similar functionality based on templates:

https://github.com/libsigcplusplus/libsigcplusplus

In a previous versions, the number of arguments was limited, because
they'd written out the templates for up to 10 arguments. I don't know if
that was changed with the advent of variadic templates.

Is there a good reason to implement your own framework instead of just
using libsigc++?

Christian

Tim Rentsch

unread,
Dec 16, 2018, 12:46:37โ€ฏPM12/16/18
to
legaliz...@mail.xmission.com (Richard) writes:

> User <aitor....@googlemail.com> spake the secret code
> <1d46e37a-e16e-4715...@googlegroups.com> thusly:
>
>> the presence of unused argument isn't a design decision, but working
>> with delegates. A function of the type EmitterFunc(int, bool, int) can
>> be connected to a function with the prototype ReceptorFunction(int,
>> bool).
>
> Delegates are not in the C++ language, so your statement seems
> disconnected from C++.
>
> Alf's point is that it's a design error to directly connect functions
> with mismatching signatures.

I think you mean type rather than signature. The two functions

int bas( int );
int foo( int );

have different signatures, but they have the same type. Certainly
one could be used in place of the other.

Tim Rentsch

unread,
Dec 16, 2018, 12:52:02โ€ฏPM12/16/18
to
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:

> On Sat, 15 Dec 2018 11:25:47 +0000
> Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
>
>> or you could derive [the arity]
>> programmatically: see an example below - you would need overloads of
>> the get_arity() function in order to cover const and non-const member
>> functions, but that is a task for you. Since the get_arity() function
>> is constexpr, you could use it together with the tuple and index list
>> approach, but that seems like overkill: instead you could drop the
>> surplus arguments as a runtime operation when invoking the receiving
>> function.
>
> By the way, this get_arity() function will not work with lambda
> expressions. But that is fine - a lambda expression is a function
> literal supplied by the programmer on the fly. You can document that if
> passing a lambda expression to your connect() function, then the
> signature of the lambda expression must match the signal's signature
> exactly, even if some arguments are unused in the lambda.

I think you mean type rather than signature. Functions have
signatures, lambda expressions do not (as the C++ standard uses
the term signature).

Chris Vine

unread,
Dec 16, 2018, 1:04:01โ€ฏPM12/16/18
to
Could you please stop replying to my posts. I find your condescension
and overall weirdness unappealing. TIA.

Alf P. Steinbach

unread,
Dec 16, 2018, 9:30:13โ€ฏPM12/16/18
to
Technically you're right.

But it's worth noting that the term "signature"

* is defined differently in C++11 and later, than in C++98/C++03,

* has a general language independent meaning more like C++03 than C++11.

The language independent meaning, and the C++98/C++03 meaning, does not
include the function name:

C++03 ยง1.3.10:
[quote]
the information about a function that participates in overload
resolution (13.3): the types of its parameters and, if the function is a
class member, the cv- qualifiers (if any) on the function itself and the
class in which the member function is declared. 2) The signature of a
function template specialization includes the types of its template
arguments (14.5.5.1).
[/quote]


Evidently for C++11 someone tried very hard to really define in detail
the meaning of "signature" so that the standard's use of that term could
be read pedantically formally, and perhaps so that that term could be
used instead of C++03 "type" in certain context (I'm not sure of that, I
haven't checked). The "signature" of a /function/ is defined as "name,
parameter type list (8.3.5), and enclosing namespace (if any)". Then
there is a definition of the "signature" of a /function template/, and a
definition of it for /function template specialization/, and a
definition of it for /class member function/, and a definition of it for
/class member function template/, and a definition of it for /class
member function template specialization/, where for the template
meanings also the return type is part of the signature.

I.e. a simple general definition that resonated well with the term's
general use, was replaced with umpteen detailed definitions that are
more unnatural in that they include the function name.

To me it reads as an attempt to define the term so that it can be used
as part of an in-group language to let language lawyers more easily
identify each other as such, and to let them identify non-lawyers.


Cheers!,

- Alf

User

unread,
Dec 18, 2018, 7:15:23โ€ฏAM12/18/18
to
I was testing how can be done. The Qt metacall function works and I was able to implement it, but I was wondering if it was possible to do it using template parameter calls and functions of different prototypes.

I'll check the libsigc++ library, but I wanted a straightforward solution, something to write with a couple a function to test.

Thanks anyway

Ross A. Finlayson

unread,
Dec 18, 2018, 8:29:20โ€ฏAM12/18/18
to
Isn't the point to remove the first one?

Removing the first parameter or argument
is probably in the runtime.

The compiler probably just made it the pointer.

Isn't C++ run-time type to the linker or what?

Oh, linking object code, eh, always so simple.

What about passing arg - sizeof(arg) and skipping zero.

Richard

unread,
Dec 20, 2018, 12:55:31โ€ฏPM12/20/18
to
[Please do not mail me a copy of your followup]

Tim Rentsch <t...@alumni.caltech.edu> spake the secret code
<kfnsgyx...@x-alumni2.alumni.caltech.edu> thusly:
This is a difference that makes no difference. Playing language
lawyer in this circumstance is boring and yields no insight.

Tim Rentsch

unread,
Mar 12, 2019, 11:42:28โ€ฏAM3/12/19
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 16.12.2018 18:46, Tim Rentsch wrote:
>
>> legaliz...@mail.xmission.com (Richard) writes:
>>
>>> User <aitor....@googlemail.com> spake the secret code
>>> <1d46e37a-e16e-4715...@googlegroups.com> thusly:
>>>
>>>> the presence of unused argument isn't a design decision, but working
>>>> with delegates. A function of the type EmitterFunc(int, bool, int) can
>>>> be connected to a function with the prototype ReceptorFunction(int,
>>>> bool).
>>>
>>> Delegates are not in the C++ language, so your statement seems
>>> disconnected from C++.
>>>
>>> Alf's point is that it's a design error to directly connect functions
>>> with mismatching signatures.
>>
>> I think you mean type rather than signature. The two functions
>>
>> int bas( int );
>> int foo( int );
>>
>> have different signatures, but they have the same type. Certainly
>> one could be used in place of the other.
>
> Technically you're right.
>
> But it's worth noting that the term "signature"
>
> * is defined differently in C++11 and later, than in C++98/C++03,
>
> [rearranged slightly for continuity]
>
> C++03 1.3.10:
> [quote]
> the information about a function that participates in overload
> resolution (13.3): the types of its parameters and, if the
> function is a class member, the cv- qualifiers (if any) on the
> function itself and the class in which the member function is
> declared. 2) The signature of a function template specialization
> includes the types of its template arguments (14.5.5.1).
> [/quote]

Interesting, I didn't know that. But I think that strengthens
the case for preferring the correct term 'type', which is right
for both pre-C++11 and C++11 onwards, to 'signature', which is
wrong in both cases. (Note that the C++98/C++03 definition of
'signature' does not include the return type.) Furthermore,
based on how the term 'signature' was used in C++98/C++03, it
looks like either (a) the definition was meant to include the
function name, or (b) needing the function name was overlooked
when writing the definition. For example, in section 17.4.3.1.3
("External linkage"), paragraph 2 says

Each global function signature declared with external
linkage in a header is reserved to the implementation to
designate that function signature with external linkage.

This statement makes sense only if 'signature' is understood
to include the function name along with the types of the
parameters.

> * has a general language independent meaning more like C++03 than
> C++11.
>
> The language independent meaning, and the C++98/C++03 meaning,
> does not include the function name.

A more accurate statement is that the term 'signature' means
different things in different languages. The original use of
'signature' in programming languages was, IIANM, in the language
Russell, where it was not associated (directly) with functions.
The ML family of languages uses 'signature' in a different way,
to define module interfaces: the signature of a module might be
called the "type" of that module. I don't know when the ML
languages introduced modules and module signatures; the usage in
Russell predates C++98 by 20 years. It's true that many people
misuse the term "signature" to mean what C and C++ call the type
of a function. But "signature" does not mean, and has never
meant (at least in C++), the same thing as the property that
Richard was alluding to in his comment.

> Evidently for C++11 someone tried very hard to really define in
> detail the meaning of "signature" so that the standard's use of
> that term could be read pedantically formally, and perhaps so that
> that term could be used instead of C++03 "type" in certain context
> (I'm not sure of that, I haven't checked). The "signature" of a
> /function/ is defined as "name, parameter type list (8.3.5), and
> enclosing namespace (if any)". Then there is a definition of the
> "signature" of a /function template/, and a definition of it for
> /function template specialization/, and a definition of it for
> /class member function/, and a definition of it for /class member
> function template/, and a definition of it for /class member
> function template specialization/, where for the template meanings
> also the return type is part of the signature.
>
> I.e. a simple general definition that resonated well with the
> term's general use, was replaced with umpteen detailed definitions
> that are more unnatural in that they include the function name.
>
> To me it reads as an attempt to define the term so that it can be
> used as part of an in-group language to let language lawyers more
> easily identify each other as such, and to let them identify
> non-lawyers.

I think you're misreading the history. Looking at usages in the
C++03 and C++98 standards, it seems clear that it was intended
all along that "signature" include the name of the function in
question. The changes in C++11 were done to correct what had
been an oversight or unintended omission. Furthermore the misuse
of "signature" to mean the type of a function didn't become
commonplace until after the C++98 standard was released. It
isn't that C++98 was following a common usage, and probably the
other way around - it was people misunderstanding the C++98
meaning to equate "signature" with "function type" that caused
"signature" to be widely misused to mean the type of a function.

Tim Rentsch

unread,
Mar 12, 2019, 12:48:38โ€ฏPM3/12/19
to
legaliz...@mail.xmission.com (Richard) writes:

> Tim Rentsch <t...@alumni.caltech.edu> spake the secret code
> <kfnsgyx...@x-alumni2.alumni.caltech.edu> thusly:
>
>> legaliz...@mail.xmission.com (Richard) writes:
>>
>>> User <aitor....@googlemail.com> spake the secret code
>>> <1d46e37a-e16e-4715...@googlegroups.com> thusly:
>>>
>>>> the presence of unused argument isn't a design decision, but working
>>>> with delegates. A function of the type EmitterFunc(int, bool, int) can
>>>> be connected to a function with the prototype ReceptorFunction(int,
>>>> bool).
>>>
>>> Delegates are not in the C++ language, so your statement seems
>>> disconnected from C++.
>>>
>>> Alf's point is that it's a design error to directly connect functions
>>> with mismatching signatures.
>>
>> I think you mean type rather than signature. The two functions
>>
>> int bas( int );
>> int foo( int );
>>
>> have different signatures, but they have the same type. Certainly
>> one could be used in place of the other.
>
> This is a difference that makes no difference. Playing language
> lawyer in this circumstance is boring and yields no insight.

There is nothing especially language lawyerish about my comment.
Being precise doesn't always imply being a language lawyer.

I'm sure some people found my comment boring. As for insight
however I think there are two:

(1) IME being careless in use of language correlates with
being careless in programming. I think it's important
to encourage good programming, and this is one aspect
of that.

(2) There is a tendency in some people to want to use
fancy words and ornate language. Usually this is a
false erudition. Every writer should read what
Ernest Hemingway wrote on the subject:

"Poor Faulkner. Does he really think big emotions come
from big words? He thinks I don't know the ten-dollar
words. I know them all right. But there are older and
simpler and better words, and those are the ones I use."

In technical discussions, precise and correct language is
always better than fancy language.

And, dare I say it, in comp.lang.c++, normally terms should be
used in the same way that the Standard(s) define them.

Tim Rentsch

unread,
Apr 9, 2019, 6:40:32โ€ฏAM4/9/19
to
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:

>> [...]
>
> Could you please stop replying to my posts. I find your condescension
> and overall weirdness unappealing. TIA.

The newsgroup is a public forum. I'm sorry if my comments came
across as condescending; that doesn't match my mindset while
I was writing nor my opinion of you generally.
0 new messages